news download themes documentation links










Toolbar.cc

00001 // Toolbar.cc for Fluxbox
00002 // Copyright (c) 2002 - 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net)
00003 //
00004 // Toolbar.cc for Blackbox - an X11 Window manager
00005 // Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
00006 //
00007 // Permission is hereby granted, free of charge, to any person obtaining a
00008 // copy of this software and associated documentation files (the "Software"),
00009 // to deal in the Software without restriction, including without limitation
00010 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011 // and/or sell copies of the Software, and to permit persons to whom the
00012 // Software is furnished to do so, subject to the following conditions:
00013 //
00014 // The above copyright notice and this permission notice shall be included in
00015 // all copies or substantial portions of the Software.
00016 //
00017 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00023 // DEALINGS IN THE SOFTWARE.
00024 
00025 // $Id: Toolbar.cc,v 1.136 2004/01/13 14:41:32 rathnor Exp $
00026 
00027 #include "Toolbar.hh"
00028 
00029 // tool
00030 #include "ToolbarItem.hh"
00031 
00032 // themes
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 // use GNU extensions
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     //default string
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 }; // end anonymous
00164 
00165 // toolbar frame
00166 Toolbar::Frame::Frame(FbTk::EventHandler &evh, int screen_num):
00167     window(screen_num, // screen (parent)
00168            0, 0, // pos
00169            10, 10, // size
00170            // event mask
00171            ButtonPressMask | ButtonReleaseMask | 
00172            EnterWindowMask | LeaveWindowMask | SubstructureNotifyMask,
00173 
00174            true) // override redirect 
00175 {
00176 
00177     FbTk::EventManager &evm = *FbTk::EventManager::instance();
00178     // add windows to eventmanager
00179     evm.add(evh, window);
00180 
00181 }
00182 
00183 Toolbar::Frame::~Frame() {
00184     FbTk::EventManager &evm = *FbTk::EventManager::instance();
00185     // remove windows from eventmanager
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     // lock rcmanager here
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     // we need to get notified when the theme is reloaded
00230     m_theme.reconfigSig().attach(this);
00231     // listen to screen size changes
00232     screen().resizeSig().attach(this);
00233     screen().reconfigureSig().attach(this); // if alpha value changes
00234 
00235     moveToLayer((*m_rc_layernum).getNum());
00236 
00237     // TODO: nls
00238     m_layermenu.setLabel("Toolbar Layer");
00239     m_placementmenu.setLabel("Toolbar Placement");
00240 
00241     m_layermenu.setInternalMenu();
00242     m_placementmenu.setInternalMenu();
00243     setupMenus();
00244     // add menu to screen
00245     screen().addConfigMenu("Toolbar", menu());
00246     
00247     // geometry settings
00248     frame.width = width;
00249     frame.height = 10;
00250     frame.bevel_w = 1;
00251     frame.grab_x = frame.grab_y = 0;
00252     
00253     // set antialias on themes
00254     m_tool_factory.updateThemes();
00255 
00256     // setup hide timer
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     // show all windows
00264     frame.window.showSubwindows();
00265     frame.window.show();
00266 
00267     scrn.resourceManager().unlock();
00268     // setup to listen to child events
00269     FbTk::EventManager::instance()->addParent(*this, window());
00270     // get everything together
00271     reconfigure(); 
00272 
00273 }
00274 
00275 Toolbar::~Toolbar() {
00276     FbTk::EventManager::instance()->remove(window());
00277     // remove menu items before we delete tools so we dont end up
00278     // with dangling pointers to old submenu items (internal menus)
00279     // from the tools
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     // we should request space if we're in autohide mode or
00301     // if the user dont want to request space for toolbar.
00302     if (doAutoHide() || *m_rc_maximize_over) {
00303         if (had_strut)
00304             screen().updateAvailableWorkspaceArea();            
00305         return;
00306     }
00307 
00308     // request area on screen
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     // parse resource tools and determine if we need to rebuild toolbar
00363 
00364     bool need_update = false;
00365     // parse and transform to lower case
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         // did we find anything that wasn't in the right place or new item?
00382         if (tool_it != tool_it_end)
00383             need_update = true;
00384     } else // sizes does not match so we update
00385         need_update = true;
00386 
00387     if (need_update) {
00388 
00389         // destroy tools and rebuild them
00390         deleteItems();
00391 
00392         m_tools = tools; // copy values
00393         
00394         if (m_tools.size()) {
00395             // make lower case
00396             transform(m_tools.begin(), m_tools.end(), 
00397                       m_tools.begin(),
00398                       FbTk::StringUtil::toLower);
00399 
00400             // create items
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             // show all items
00411             frame.window.showSubwindows();
00412         }
00413     }
00414 
00415     if (doAutoHide())
00416         m_hide_timer.start();
00417 
00418     frame.bevel_w = theme().bevelWidth();
00419     // destroy shape if the theme wasn't specified with one,
00420     // or create one 
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     // recallibrate size
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     // render frame window
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     // we're done with all resizing and stuff now we can request a new 
00465     // area to be reserved on screen
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) //mousewheel scroll up
00506         screen().nextWorkspace(1);
00507     else if (re.button == 5)    //mousewheel scroll down
00508         screen().prevWorkspace(1);
00509 }
00510 
00511 void Toolbar::enterNotifyEvent(XCrossingEvent &not_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     // still inside?
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     // either screen reconfigured or theme was reloaded
00563     
00564     reconfigure();
00565 }
00566 
00567 void Toolbar::setPlacement(Toolbar::Placement where) {
00568     // disable vertical toolbar
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     // max height of each toolbar items font...
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     // should we flipp sizes?
00616     if (isVertical()) {
00617         frame.width = frame.height;
00618         frame.height = head_h * (*m_rc_width_percent) / 100;
00619 
00620     } // else horizontal toolbar
00621 
00622 
00623     // So we get at least one pixel visible in hidden mode
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: // default is 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     // toggle hidden
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); // min/max value
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         // TODO: nls (main label plus menu heading
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     // setup items in placement menu
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     // create items in sub menu
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     // lock this
00871     m_resize_lock = true;
00872     // calculate size for fixed items
00873     ItemList::iterator item_it = m_item_list.begin();
00874     ItemList::iterator item_it_end = m_item_list.end();
00875     int fixed_width = 0; // combined size of all fixed items
00876     int fixed_items = 0; // number of fixed items
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     // calculate what's going to be le ft over to the relative sized items
00888     int relative_width = 0;
00889     int rounding_error = 0;
00890     if (fixed_items == 0) // no fixed items, then the rest is the entire width
00891         relative_width = width();
00892     else {
00893         if (relative_items == 0)
00894             relative_width = 0;
00895         else { // size left after fixed items / number of relative items
00896             relative_width = (width() - fixed_width)/relative_items;
00897             rounding_error = width() - fixed_width - relative_items*relative_width;
00898         }
00899     }
00900     // now move and resize the items
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) { // distribute rounding error over all relatives
00913                 extra = 1;
00914                 --rounding_error;
00915             }
00916 
00917             (*item_it)->moveResize(next_x, -borderW, extra + relative_width-2*borderW, height());
00918         } else { // fixed size
00919             (*item_it)->moveResize(next_x, -borderW,
00920                                    (*item_it)->width(), height()); 
00921         }
00922         next_x += (*item_it)->width() + borderW*2;
00923     }
00924     // unlock
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 }

Fluxbox CVS-Jan-2003




      



Got comments about the page? Send them to webmaster.
If you have general Fluxbox related questions ask them on our irc channel or mailing lists.

Show Source








Designed by aLEczapKA