00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "Toolbar.hh"
00028
00029
00030 #include "ToolbarItem.hh"
00031
00032
00033 #include "ToolbarTheme.hh"
00034
00035 #include "I18n.hh"
00036 #include "fluxbox.hh"
00037 #include "Screen.hh"
00038 #include "IntResMenuItem.hh"
00039 #include "BoolMenuItem.hh"
00040 #include "Xinerama.hh"
00041 #include "Strut.hh"
00042 #include "CommandParser.hh"
00043
00044 #include "FbTk/ImageControl.hh"
00045 #include "FbTk/MacroCommand.hh"
00046 #include "FbTk/EventManager.hh"
00047 #include "FbTk/SimpleCommand.hh"
00048 #include "FbTk/StringUtil.hh"
00049
00050
00051
00052 #ifndef _GNU_SOURCE
00053 #define _GNU_SOURCE
00054 #endif // _GNU_SOURCE
00055
00056 #ifdef HAVE_CONFIG_H
00057 #include "config.h"
00058 #endif // HAVE_CONFIG_H
00059
00060 #include "Shape.hh"
00061
00062 #include <X11/Xutil.h>
00063 #include <X11/keysym.h>
00064
00065 #include <cstring>
00066 #include <cstdio>
00067 #include <iterator>
00068
00069 #include <iostream>
00070
00071 using namespace std;
00072
00073 template<>
00074 void FbTk::Resource<Toolbar::Placement>::
00075 setFromString(const char *strval) {
00076 if (strcasecmp(strval, "TopLeft")==0)
00077 m_value = Toolbar::TOPLEFT;
00078 else if (strcasecmp(strval, "BottomLeft")==0)
00079 m_value = Toolbar::BOTTOMLEFT;
00080 else if (strcasecmp(strval, "TopCenter")==0)
00081 m_value = Toolbar::TOPCENTER;
00082 else if (strcasecmp(strval, "BottomCenter")==0)
00083 m_value = Toolbar::BOTTOMCENTER;
00084 else if (strcasecmp(strval, "TopRight")==0)
00085 m_value = Toolbar::TOPRIGHT;
00086 else if (strcasecmp(strval, "BottomRight")==0)
00087 m_value = Toolbar::BOTTOMRIGHT;
00088 else if (strcasecmp(strval, "LeftTop") == 0)
00089 m_value = Toolbar::LEFTTOP;
00090 else if (strcasecmp(strval, "LeftCenter") == 0)
00091 m_value = Toolbar::LEFTCENTER;
00092 else if (strcasecmp(strval, "LeftBottom") == 0)
00093 m_value = Toolbar::LEFTBOTTOM;
00094 else if (strcasecmp(strval, "RightTop") == 0)
00095 m_value = Toolbar::RIGHTTOP;
00096 else if (strcasecmp(strval, "RightCenter") == 0)
00097 m_value = Toolbar::RIGHTCENTER;
00098 else if (strcasecmp(strval, "RightBottom") == 0)
00099 m_value = Toolbar::RIGHTBOTTOM;
00100 else
00101 setDefaultValue();
00102 }
00103
00104 string FbTk::Resource<Toolbar::Placement>::
00105 getString() {
00106 switch (m_value) {
00107 case Toolbar::TOPLEFT:
00108 return string("TopLeft");
00109 break;
00110 case Toolbar::BOTTOMLEFT:
00111 return string("BottomLeft");
00112 break;
00113 case Toolbar::TOPCENTER:
00114 return string("TopCenter");
00115 break;
00116 case Toolbar::BOTTOMCENTER:
00117 return string("BottomCenter");
00118 break;
00119 case Toolbar::TOPRIGHT:
00120 return string("TopRight");
00121 break;
00122 case Toolbar::BOTTOMRIGHT:
00123 return string("BottomRight");
00124 break;
00125 case Toolbar::LEFTTOP:
00126 return string("LeftTop");
00127 break;
00128 case Toolbar::LEFTCENTER:
00129 return string("LeftCenter");
00130 break;
00131 case Toolbar::LEFTBOTTOM:
00132 return string("LeftBottom");
00133 break;
00134 case Toolbar::RIGHTTOP:
00135 return string("RightTop");
00136 break;
00137 case Toolbar::RIGHTCENTER:
00138 return string("RightCenter");
00139 break;
00140 case Toolbar::RIGHTBOTTOM:
00141 return string("RightBottom");
00142 break;
00143 }
00144
00145 return string("BottomCenter");
00146 }
00147
00148
00149 namespace {
00150 class SetToolbarPlacementCmd: public FbTk::Command {
00151 public:
00152 SetToolbarPlacementCmd(Toolbar &tbar, Toolbar::Placement place):m_tbar(tbar), m_place(place) { }
00153 void execute() {
00154 m_tbar.setPlacement(m_place);
00155 m_tbar.reconfigure();
00156 Fluxbox::instance()->save_rc();
00157 }
00158 private:
00159 Toolbar &m_tbar;
00160 Toolbar::Placement m_place;
00161 };
00162
00163 };
00164
00165
00166 Toolbar::Frame::Frame(FbTk::EventHandler &evh, int screen_num):
00167 window(screen_num,
00168 0, 0,
00169 10, 10,
00170
00171 ButtonPressMask | ButtonReleaseMask |
00172 EnterWindowMask | LeaveWindowMask | SubstructureNotifyMask,
00173
00174 true)
00175 {
00176
00177 FbTk::EventManager &evm = *FbTk::EventManager::instance();
00178
00179 evm.add(evh, window);
00180
00181 }
00182
00183 Toolbar::Frame::~Frame() {
00184 FbTk::EventManager &evm = *FbTk::EventManager::instance();
00185
00186 evm.remove(window);
00187 }
00188
00189 Toolbar::Toolbar(BScreen &scrn, FbTk::XLayer &layer, size_t width):
00190 m_hidden(false),
00191 frame(*this, scrn.screenNumber()),
00192 m_window_pm(0),
00193 m_screen(scrn),
00194 m_layermenu(scrn.menuTheme(),
00195 scrn.imageControl(),
00196 *scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
00197 this,
00198 true),
00199 m_placementmenu(scrn.menuTheme(),
00200 scrn.imageControl(),
00201 *scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
00202 m_toolbarmenu(scrn.menuTheme(),
00203 scrn.imageControl(),
00204 *scrn.layerManager().getLayer(Fluxbox::instance()->getMenuLayer())),
00205 m_theme(scrn.screenNumber()),
00206 m_layeritem(frame.window, layer),
00207 m_tool_factory(scrn),
00208 m_strut(0),
00209
00210 m_rc_auto_hide(scrn.resourceManager().lock(), false,
00211 scrn.name() + ".toolbar.autoHide", scrn.altName() + ".Toolbar.AutoHide"),
00212 m_rc_maximize_over(scrn.resourceManager(), false,
00213 scrn.name() + ".toolbar.maxOver", scrn.altName() + ".Toolbar.MaxOver"),
00214 m_rc_visible(scrn.resourceManager(), true, scrn.name() + ".toolbar.visible", scrn.altName() + ".Toolbar.Visible"),
00215 m_rc_width_percent(scrn.resourceManager(), 65,
00216 scrn.name() + ".toolbar.widthPercent", scrn.altName() + ".Toolbar.WidthPercent"),
00217 m_rc_layernum(scrn.resourceManager(), Fluxbox::Layer(Fluxbox::instance()->getDesktopLayer()),
00218 scrn.name() + ".toolbar.layer", scrn.altName() + ".Toolbar.Layer"),
00219 m_rc_on_head(scrn.resourceManager(), 0,
00220 scrn.name() + ".toolbar.onhead", scrn.altName() + ".Toolbar.onHead"),
00221 m_rc_placement(scrn.resourceManager(), Toolbar::BOTTOMCENTER,
00222 scrn.name() + ".toolbar.placement", scrn.altName() + ".Toolbar.Placement"),
00223 m_rc_height(scrn.resourceManager(), 0, scrn.name() + ".toolbar.height", scrn.altName() + ".Toolbar.Height"),
00224 m_rc_tools(scrn.resourceManager(), "workspacename, prevworkspace, nextworkspace, iconbar, systemtray, prevwindow, nextwindow, clock",
00225 scrn.name() + ".toolbar.tools", scrn.altName() + ".Toolbar.Tools"),
00226 m_shape(new Shape(frame.window, 0)),
00227 m_resize_lock(false) {
00228
00229
00230 m_theme.reconfigSig().attach(this);
00231
00232 screen().resizeSig().attach(this);
00233 screen().reconfigureSig().attach(this);
00234
00235 moveToLayer((*m_rc_layernum).getNum());
00236
00237
00238 m_layermenu.setLabel("Toolbar Layer");
00239 m_placementmenu.setLabel("Toolbar Placement");
00240
00241 m_layermenu.setInternalMenu();
00242 m_placementmenu.setInternalMenu();
00243 setupMenus();
00244
00245 screen().addConfigMenu("Toolbar", menu());
00246
00247
00248 frame.width = width;
00249 frame.height = 10;
00250 frame.bevel_w = 1;
00251 frame.grab_x = frame.grab_y = 0;
00252
00253
00254 m_tool_factory.updateThemes();
00255
00256
00257 m_hide_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay());
00258 FbTk::RefCount<FbTk::Command> toggle_hidden(new FbTk::SimpleCommand<Toolbar>(*this, &Toolbar::toggleHidden));
00259 m_hide_timer.setCommand(toggle_hidden);
00260 m_hide_timer.fireOnce(true);
00261
00262
00263
00264 frame.window.showSubwindows();
00265 frame.window.show();
00266
00267 scrn.resourceManager().unlock();
00268
00269 FbTk::EventManager::instance()->addParent(*this, window());
00270
00271 reconfigure();
00272
00273 }
00274
00275 Toolbar::~Toolbar() {
00276 FbTk::EventManager::instance()->remove(window());
00277
00278
00279
00280 menu().removeAll();
00281
00282 deleteItems();
00283 clearStrut();
00284
00285 if (m_window_pm)
00286 screen().imageControl().removeImage(m_window_pm);
00287 }
00288
00289 void Toolbar::clearStrut() {
00290 if (m_strut) {
00291 screen().clearStrut(m_strut);
00292 m_strut = 0;
00293 }
00294 }
00295
00296 void Toolbar::updateStrut() {
00297
00298 bool had_strut = m_strut ? true : false;
00299 clearStrut();
00300
00301
00302 if (doAutoHide() || *m_rc_maximize_over) {
00303 if (had_strut)
00304 screen().updateAvailableWorkspaceArea();
00305 return;
00306 }
00307
00308
00309 int top = 0, bottom = 0, left = 0, right = 0;
00310 switch (placement()) {
00311 case TOPLEFT:
00312 case TOPCENTER:
00313 case TOPRIGHT:
00314 top = height();
00315 break;
00316 case BOTTOMLEFT:
00317 case BOTTOMCENTER:
00318 case BOTTOMRIGHT:
00319 bottom = height();
00320 break;
00321 case RIGHTTOP:
00322 case RIGHTCENTER:
00323 case RIGHTBOTTOM:
00324 right = width();
00325 break;
00326 case LEFTTOP:
00327 case LEFTCENTER:
00328 case LEFTBOTTOM:
00329 left = width();
00330 break;
00331 };
00332 m_strut = screen().requestStrut(left, right, top, bottom);
00333 screen().updateAvailableWorkspaceArea();
00334 }
00335
00336 bool Toolbar::isVertical() const {
00337 return (placement() == RIGHTCENTER ||
00338 placement() == RIGHTTOP ||
00339 placement() == RIGHTBOTTOM ||
00340 placement() == LEFTCENTER ||
00341 placement() == LEFTTOP ||
00342 placement() == LEFTBOTTOM);
00343 }
00344
00345
00346 void Toolbar::raise() {
00347 m_layeritem.raise();
00348 }
00349
00350 void Toolbar::lower() {
00351 m_layeritem.lower();
00352 }
00353
00354 void Toolbar::reconfigure() {
00355 updateVisibleState();
00356
00357 if (!doAutoHide() && isHidden())
00358 toggleHidden();
00359
00360 m_tool_factory.updateThemes();
00361
00362
00363
00364 bool need_update = false;
00365
00366 std::list<std::string> tools;
00367 FbTk::StringUtil::stringtok(tools, *m_rc_tools, ", ");
00368 transform(tools.begin(),
00369 tools.end(),
00370 tools.begin(),
00371 FbTk::StringUtil::toLower);
00372
00373 if (tools.size() == m_tools.size() && tools.size() != 0) {
00374 StringList::const_iterator tool_it = tools.begin();
00375 StringList::const_iterator current_tool_it = m_tools.begin();
00376 StringList::const_iterator tool_it_end = tools.end();
00377 for (; tool_it != tool_it_end; ++tool_it, ++current_tool_it) {
00378 if (*current_tool_it != *tool_it)
00379 break;
00380 }
00381
00382 if (tool_it != tool_it_end)
00383 need_update = true;
00384 } else
00385 need_update = true;
00386
00387 if (need_update) {
00388
00389
00390 deleteItems();
00391
00392 m_tools = tools;
00393
00394 if (m_tools.size()) {
00395
00396 transform(m_tools.begin(), m_tools.end(),
00397 m_tools.begin(),
00398 FbTk::StringUtil::toLower);
00399
00400
00401 StringList::const_iterator item_it = m_tools.begin();
00402 StringList::const_iterator item_it_end = m_tools.end();
00403 for (; item_it != item_it_end; ++item_it) {
00404 ToolbarItem *item = m_tool_factory.create(*item_it, frame.window, *this);
00405 if (item == 0)
00406 continue;
00407 m_item_list.push_back(item);
00408
00409 }
00410
00411 frame.window.showSubwindows();
00412 }
00413 }
00414
00415 if (doAutoHide())
00416 m_hide_timer.start();
00417
00418 frame.bevel_w = theme().bevelWidth();
00419
00420
00421 if (theme().shape() == false && m_shape.get())
00422 m_shape.reset(0);
00423 else if (theme().shape() && m_shape.get() == 0) {
00424 m_shape.reset(new Shape(frame.window, 0));
00425 }
00426
00427
00428 setPlacement(placement());
00429
00430 if (isHidden()) {
00431 frame.window.moveResize(frame.x_hidden, frame.y_hidden,
00432 frame.width, frame.height);
00433 } else {
00434 frame.window.moveResize(frame.x, frame.y,
00435 frame.width, frame.height);
00436 }
00437
00438
00439 Pixmap tmp = m_window_pm;
00440 if (!theme().toolbar().usePixmap()) {
00441 m_window_pm = 0;
00442 frame.window.setBackgroundColor(theme().toolbar().color());
00443 } else {
00444 m_window_pm = screen().imageControl().renderImage(frame.window.width(), frame.window.height(),
00445 theme().toolbar());
00446 frame.window.setBackgroundPixmap(m_window_pm);
00447 }
00448 if (tmp)
00449 screen().imageControl().removeImage(tmp);
00450
00451 frame.window.setBorderColor(theme().border().color());
00452 frame.window.setBorderWidth(theme().border().width());
00453 frame.window.setAlpha(theme().alpha());
00454 frame.window.clear();
00455 frame.window.updateTransparent();
00456
00457 if (theme().shape() && m_shape.get())
00458 m_shape->update();
00459
00460
00461 rearrangeItems();
00462
00463 menu().reconfigure();
00464
00465
00466 updateStrut();
00467
00468 }
00469
00470
00471
00472 void Toolbar::buttonPressEvent(XButtonEvent &be) {
00473 if (be.button != 3)
00474 return;
00475
00476 screen().hideMenus();
00477
00478 if (! menu().isVisible()) {
00479 int x, y;
00480
00481 x = be.x_root - (menu().width() / 2);
00482 y = be.y_root - (menu().height() / 2);
00483
00484 if (x < 0)
00485 x = 0;
00486 else if (x + menu().width() > screen().width())
00487 x = screen().width() - menu().width();
00488
00489 if (y < 0)
00490 y = 0;
00491 else if (y + menu().height() > screen().height())
00492 y = screen().height() - menu().height();
00493
00494 menu().move(x, y);
00495 menu().show();
00496 } else
00497 menu().hide();
00498
00499 }
00500
00501
00502 void Toolbar::buttonReleaseEvent(XButtonEvent &re) {
00503 if (re.button == 1)
00504 raise();
00505 else if (re.button == 4)
00506 screen().nextWorkspace(1);
00507 else if (re.button == 5)
00508 screen().prevWorkspace(1);
00509 }
00510
00511 void Toolbar::enterNotifyEvent(XCrossingEvent ¬_used) {
00512 if (! doAutoHide()) {
00513 if (isHidden())
00514 toggleHidden();
00515 return;
00516 }
00517
00518 if (isHidden()) {
00519 if (! m_hide_timer.isTiming())
00520 m_hide_timer.start();
00521 } else {
00522 if (m_hide_timer.isTiming())
00523 m_hide_timer.stop();
00524 }
00525 }
00526
00527 void Toolbar::leaveNotifyEvent(XCrossingEvent &event) {
00528 if (! doAutoHide())
00529 return;
00530
00531 if (event.x_root > x() && event.x_root <= (int)(x() + width()) &&
00532 event.y_root > y() && event.y_root <= (int)(y() + height()))
00533 return;
00534
00535 if (isHidden()) {
00536 if (m_hide_timer.isTiming())
00537 m_hide_timer.stop();
00538 } else if (! menu().isVisible() && ! m_hide_timer.isTiming())
00539 m_hide_timer.start();
00540
00541 }
00542
00543
00544 void Toolbar::exposeEvent(XExposeEvent &ee) {
00545 if (ee.window == frame.window) {
00546 frame.window.clearArea(ee.x, ee.y,
00547 ee.width, ee.height);
00548 frame.window.updateTransparent(ee.x, ee.y,
00549 ee.width, ee.height);
00550 }
00551 }
00552
00553
00554 void Toolbar::handleEvent(XEvent &event) {
00555 if (event.type == ConfigureNotify &&
00556 event.xconfigure.window != window().window())
00557 rearrangeItems();
00558 }
00559
00560 void Toolbar::update(FbTk::Subject *subj) {
00561
00562
00563
00564 reconfigure();
00565 }
00566
00567 void Toolbar::setPlacement(Toolbar::Placement where) {
00568
00569 switch (where) {
00570 case LEFTTOP:
00571 case LEFTCENTER:
00572 case LEFTBOTTOM:
00573 case RIGHTTOP:
00574 case RIGHTCENTER:
00575 case RIGHTBOTTOM:
00576 where = BOTTOMCENTER;
00577 break;
00578 default:
00579 break;
00580 }
00581
00582 *m_rc_placement = where;
00583 int head_x = 0,
00584 head_y = 0,
00585 head_w = screen().width(),
00586 head_h = screen().height();
00587
00588 if (screen().hasXinerama()) {
00589 int head = *m_rc_on_head;
00590 head_x = screen().getHeadX(head);
00591 head_y = screen().getHeadY(head);
00592 head_w = screen().getHeadWidth(head);
00593 head_h = screen().getHeadHeight(head);
00594 }
00595
00596 frame.width = head_w * (*m_rc_width_percent) / 100;
00598
00599 unsigned int max_height = m_tool_factory.maxFontHeight();
00600
00601 if (theme().height() > 0)
00602 max_height = theme().height();
00603
00604 if (*m_rc_height > 0 && *m_rc_height < 100)
00605 max_height = *m_rc_height;
00606
00607 frame.height = max_height;
00608
00609 frame.height += 2;
00610 frame.height += (frame.bevel_w * 2);
00611
00612 int bevel_width = theme().bevelWidth();
00613 int border_width = theme().border().width();
00614
00615
00616 if (isVertical()) {
00617 frame.width = frame.height;
00618 frame.height = head_h * (*m_rc_width_percent) / 100;
00619
00620 }
00621
00622
00623
00624 if (bevel_width <= border_width)
00625 bevel_width = border_width + 1;
00626
00627 switch (where) {
00628 case TOPLEFT:
00629 frame.x = head_x;
00630 frame.y = head_y;
00631 frame.x_hidden = head_x;
00632 frame.y_hidden = head_y + bevel_width - border_width - frame.height;
00633 if (m_shape.get())
00634 m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
00635 break;
00636
00637 case BOTTOMLEFT:
00638 frame.x = head_x;
00639 frame.y = head_y + head_h - frame.height - border_width*2;
00640 frame.x_hidden = head_x;
00641 frame.y_hidden = head_y + head_h - bevel_width - border_width;
00642 if (m_shape.get())
00643 m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
00644 break;
00645
00646 case TOPCENTER:
00647 frame.x = head_x + (head_w - frame.width) / 2;
00648 frame.y = head_y;
00649 frame.x_hidden = frame.x;
00650 frame.y_hidden = head_y + bevel_width - border_width - frame.height;
00651 if (m_shape.get())
00652 m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
00653 break;
00654 case TOPRIGHT:
00655 frame.x = head_x + head_w - frame.width - border_width*2;
00656 frame.y = head_y;
00657 frame.x_hidden = frame.x;
00658 if (m_shape.get())
00659 m_shape->setPlaces(Shape::BOTTOMRIGHT | Shape::BOTTOMLEFT);
00660 break;
00661
00662 case BOTTOMRIGHT:
00663 frame.x = head_x + head_w - frame.width - border_width*2;
00664 frame.y = head_y + head_h - frame.height - border_width*2;
00665 frame.x_hidden = frame.x;
00666 frame.y_hidden = head_y + head_h - bevel_width - border_width;
00667 if (m_shape.get())
00668 m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
00669 break;
00670
00671 case BOTTOMCENTER:
00672 default:
00673 frame.x = head_x + (head_w - frame.width) / 2;
00674 frame.y = head_y + head_h - frame.height - border_width*2;
00675 frame.x_hidden = frame.x;
00676 frame.y_hidden = head_y + head_h - bevel_width - border_width;
00677 if (m_shape.get())
00678 m_shape->setPlaces(Shape::TOPRIGHT | Shape::TOPLEFT);
00679 break;
00680 case LEFTCENTER:
00681 frame.x = head_x;
00682 frame.y = head_y + (head_h - frame.height)/2;
00683 frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
00684 frame.y_hidden = frame.y;
00685 if (m_shape.get())
00686 m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
00687 break;
00688 case LEFTTOP:
00689 frame.x = head_x;
00690 frame.y = head_y;
00691 frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
00692 frame.y_hidden = frame.y;
00693 if (m_shape.get())
00694 m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
00695 break;
00696 case LEFTBOTTOM:
00697 frame.x = head_x;
00698 frame.y = head_y + head_h - frame.height - border_width*2;
00699 frame.x_hidden = frame.x - frame.width + bevel_width + border_width;
00700 frame.y_hidden = frame.y;
00701 if (m_shape.get())
00702 m_shape->setPlaces(Shape::TOPRIGHT | Shape::BOTTOMRIGHT);
00703 break;
00704 case RIGHTCENTER:
00705 frame.x = head_x + head_w - frame.width - border_width*2;
00706 frame.y = head_y + (head_h - frame.height)/2;
00707 frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
00708 frame.y_hidden = frame.y;
00709 if (m_shape.get())
00710 m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
00711 break;
00712 case RIGHTTOP:
00713 frame.x = head_x + head_w - frame.width - border_width*2;
00714 frame.y = head_y;
00715 frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
00716 frame.y_hidden = frame.y;
00717 if (m_shape.get())
00718 m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
00719 break;
00720 case RIGHTBOTTOM:
00721 frame.x = head_x + head_w - frame.width - border_width*2;
00722 frame.y = head_y + head_h - frame.height - border_width*2;
00723 frame.x_hidden = frame.x + frame.width - bevel_width - border_width;
00724 frame.y_hidden = frame.y;
00725 if (m_shape.get())
00726 m_shape->setPlaces(Shape::TOPLEFT | Shape::BOTTOMLEFT);
00727 break;
00728 }
00729 }
00730
00731 void Toolbar::updateVisibleState() {
00732 *m_rc_visible ? frame.window.show() : frame.window.hide();
00733 }
00734
00735 void Toolbar::toggleHidden() {
00736
00737
00738
00739 m_hidden = ! m_hidden;
00740 if (isHidden())
00741 frame.window.move(frame.x_hidden, frame.y_hidden);
00742 else
00743 frame.window.move(frame.x, frame.y);
00744
00745 }
00746
00747 void Toolbar::moveToLayer(int layernum) {
00748 m_layeritem.moveToLayer(layernum);
00749 *m_rc_layernum = layernum;
00750 }
00751
00752 void Toolbar::setupMenus() {
00753 const I18n &i18n = *I18n::instance();
00754 using namespace FBNLS;
00755 using namespace FbTk;
00756
00757 typedef RefCount<Command> RefCommand;
00758 typedef SimpleCommand<Toolbar> ToolbarCommand;
00759
00761
00762
00763 RefCommand start_edit(CommandParser::instance().parseLine("setworkspacenamedialog"));
00764 menu().insert(i18n.getMessage(FBNLS::ToolbarSet, FBNLS::ToolbarEditWkspcName,
00765 "Edit current workspace name"),
00766 start_edit);
00767
00768 menu().setLabel(i18n.getMessage(FBNLS::ToolbarSet, FBNLS::ToolbarToolbarTitle,
00769 "Toolbar"));
00770
00771 MenuItem *toolbar_menuitem = new IntResMenuItem("Toolbar width percent",
00772 m_rc_width_percent,
00773 0, 100);
00774
00775
00776 RefCommand reconfig_toolbar(new ToolbarCommand(*this, &Toolbar::reconfigure));
00777 RefCommand save_resources(CommandParser::instance().parseLine("saverc"));
00778 MacroCommand *toolbar_menuitem_macro = new MacroCommand();
00779 toolbar_menuitem_macro->add(reconfig_toolbar);
00780 toolbar_menuitem_macro->add(save_resources);
00781
00782 RefCommand reconfig_toolbar_and_save_resource(toolbar_menuitem_macro);
00783 toolbar_menuitem->setCommand(reconfig_toolbar_and_save_resource);
00784
00785 menu().insert(toolbar_menuitem);
00786
00787 menu().insert(new BoolMenuItem(i18n.getMessage(FBNLS::CommonSet, FBNLS::CommonAutoHide,
00788 "Auto hide"),
00789 *m_rc_auto_hide,
00790 reconfig_toolbar_and_save_resource));
00791
00792 MacroCommand *visible_macro = new MacroCommand();
00793 RefCommand toggle_visible(new ToolbarCommand(*this, &Toolbar::updateVisibleState));
00794 visible_macro->add(toggle_visible);
00795 visible_macro->add(save_resources);
00796 RefCommand toggle_visible_cmd(visible_macro);
00797 menu().insert(new BoolMenuItem("Visible", *m_rc_visible, toggle_visible_cmd));
00798
00799 menu().insert(new BoolMenuItem("Maximize Over", *m_rc_maximize_over,
00800 reconfig_toolbar_and_save_resource));
00801 menu().insert("Layer...", &layermenu());
00802
00803
00804
00805 if (screen().hasXinerama()) {
00806
00807 menu().insert("On Head...", new XineramaHeadMenu<Toolbar>(screen().menuTheme(),
00808 screen(),
00809 screen().imageControl(),
00810 *screen().layerManager().getLayer(Fluxbox::instance()->getMenuLayer()),
00811 *this,
00812 "Toolbar on Head"));
00813 }
00814
00815
00816 struct {
00817 int set;
00818 int base;
00819 const char *default_str;
00820 Toolbar::Placement placement;
00821 } place_menu[] = {
00822 {0, 0, "Top Left", Toolbar::TOPLEFT},
00823
00824 {0, 0, "Left Top", Toolbar::LEFTTOP},
00825 {0, 0, "Left Center", Toolbar::LEFTCENTER},
00826 {0, 0, "Left Bottom", Toolbar::LEFTBOTTOM},
00827
00828 {0, 0, "Bottom Left", Toolbar::BOTTOMLEFT},
00829 {0, 0, "Top Center", Toolbar::TOPCENTER},
00830 {0, 0, 0, Toolbar::TOPCENTER},
00831 {0, 0, 0, Toolbar::BOTTOMCENTER},
00832 {0, 0, 0, Toolbar::BOTTOMCENTER},
00833 {0, 0, "Bottom Center", Toolbar::BOTTOMCENTER},
00834 {0, 0, "Top Right", Toolbar::TOPRIGHT},
00835
00836 {0, 0, "Right Top", Toolbar::RIGHTTOP},
00837 {0, 0, "Right Center", Toolbar::RIGHTCENTER},
00838 {0, 0, "Right Bottom", Toolbar::RIGHTBOTTOM},
00839
00840 {0, 0, "Bottom Right", Toolbar::BOTTOMRIGHT}
00841 };
00842 placementMenu().setMinimumSublevels(3);
00843
00844 for (size_t i=0; i<15; ++i) {
00845 if (place_menu[i].default_str == 0) {
00846 placementMenu().insert("");
00847 } else {
00848 const char *i18n_str = i18n.getMessage(place_menu[i].set,
00849 place_menu[i].base,
00850 place_menu[i].default_str);
00851 RefCommand setplace(new SetToolbarPlacementCmd(*this, place_menu[i].placement));
00852 placementMenu().insert(i18n_str, setplace);
00853
00854 }
00855 }
00856 menu().insert("Placement", &placementMenu());
00857 placementMenu().update();
00858 menu().update();
00859 }
00860
00861 void Toolbar::saveOnHead(int head) {
00862 m_rc_on_head = head;
00863 reconfigure();
00864 }
00865
00866 void Toolbar::rearrangeItems() {
00867 if (m_resize_lock || screen().isShuttingdown() ||
00868 m_item_list.empty())
00869 return;
00870
00871 m_resize_lock = true;
00872
00873 ItemList::iterator item_it = m_item_list.begin();
00874 ItemList::iterator item_it_end = m_item_list.end();
00875 int fixed_width = 0;
00876 int fixed_items = 0;
00877 int relative_items = 0;
00878 for (; item_it != item_it_end; ++item_it) {
00879 if ((*item_it)->type() == ToolbarItem::FIXED && (*item_it)->active()) {
00880 fixed_width += (*item_it)->width() + (*item_it)->borderWidth()*2;
00881 fixed_items++;
00882 } else if ((*item_it)->type() == ToolbarItem::RELATIVE && (*item_it)->active()) {
00883 relative_items++;
00884 }
00885 }
00886
00887
00888 int relative_width = 0;
00889 int rounding_error = 0;
00890 if (fixed_items == 0)
00891 relative_width = width();
00892 else {
00893 if (relative_items == 0)
00894 relative_width = 0;
00895 else {
00896 relative_width = (width() - fixed_width)/relative_items;
00897 rounding_error = width() - fixed_width - relative_items*relative_width;
00898 }
00899 }
00900
00901 int next_x = 0;
00902 for (item_it = m_item_list.begin(); item_it != item_it_end; ++item_it) {
00903 if (!(*item_it)->active()) {
00904 (*item_it)->hide();
00905 continue;
00906 }
00907
00908 int borderW = (*item_it)->borderWidth();
00909 (*item_it)->show();
00910 if ((*item_it)->type() == ToolbarItem::RELATIVE) {
00911 int extra = 0;
00912 if (rounding_error != 0) {
00913 extra = 1;
00914 --rounding_error;
00915 }
00916
00917 (*item_it)->moveResize(next_x, -borderW, extra + relative_width-2*borderW, height());
00918 } else {
00919 (*item_it)->moveResize(next_x, -borderW,
00920 (*item_it)->width(), height());
00921 }
00922 next_x += (*item_it)->width() + borderW*2;
00923 }
00924
00925 m_resize_lock = false;
00926 frame.window.clear();
00927 frame.window.updateTransparent();
00928
00929 }
00930
00931 void Toolbar::deleteItems() {
00932 while (!m_item_list.empty()) {
00933 delete m_item_list.back();
00934 m_item_list.pop_back();
00935 }
00936 m_tools.clear();
00937 }