Added SimpleObserver class. This class works in the same way as the SimpleCommand class. Use it with the makeObserver function. It calls the receiver's member function when the subject sends a signal.
@@ -44,7 +44,7 @@ Resource.hh Resource.cc \
StringUtil.hh StringUtil.cc Parser.hh Parser.cc \ RegExp.hh RegExp.cc \ FbString.hh FbString.cc \ - Subject.hh Subject.cc Observer.hh Observer.cc \ + Subject.hh Subject.cc Observer.hh Observer.cc SimpleObserver.hh \ Transparent.hh Transparent.cc \ FbPixmap.hh FbPixmap.cc \ FbDrawable.hh FbDrawable.cc \
@@ -0,0 +1,70 @@
+// SimpleObserver.hh +// Copyright (c) 2008 Fluxbox Team (fluxgen at fluxbox dot org) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "Observer.hh" +#include "SimpleCommand.hh" + +namespace FbTk { + +/** Functor for observers, instead of using this directly use makeObserver. + * Usage: + * @code + * class SomeClass { + * public: + * void doAction(); + * }; + * + * SomeClass some; + * + * Observer* obs = makeProxyObserver(some, &SomeClass::doAction); + * SomeSubject subj; + * subj.attach(obs); + * @endcode + */ +template <typename Receiver> +class SimpleObserver: public Observer { +public: + typedef void (Receiver::* Action)(); + SimpleObserver(Receiver &r, Action a): + m_receiver(r), m_action(a) { + + } + void update(Subject *changedSubj) { + (m_receiver.*m_action)(); + } +private: + Receiver &m_receiver; + Action m_action; +}; + +// Helpers +/** Creates an observer that takes no arguments. + * @param receiver The receiving instance. + * @param action A function in the receiving class. + * @return allocated simple observer. @see SimpleObserver + */ +template <typename Receiver, typename Action> +Observer *makeObserver(Receiver &receiver, Action action) { + return new SimpleObserver<Receiver>( receiver, action ); +} + +} +
@@ -1,5 +1,5 @@
// SendToMenu.cc for Fluxbox -// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) +// Copyright (c) 2003 - 2008 Henrik Kinnunen (fluxgen at fluxbox dot org) // and Simon Bowden (rathnor at users.sourceforge.net) // // Permission is hereby granted, free of charge, to any person obtaining a@@ -31,6 +31,7 @@ #include "Layer.hh"
#include "FbTk/MultiButtonMenuItem.hh" #include "FbTk/Command.hh" +#include "FbTk/SimpleObserver.hh" class SendToCmd: public FbTk::Command<void> { public:@@ -54,24 +55,21 @@ // listen to:
// workspace count signal // workspace names signal // current workspace signal - screen.workspaceCountSig().attach(this); - screen.workspaceNamesSig().attach(this); - screen.currentWorkspaceSig().attach(this); + m_rebuildObs = makeObserver(*this, &SendToMenu::rebuildMenu); + screen.workspaceCountSig().attach(m_rebuildObs); + screen.workspaceNamesSig().attach(m_rebuildObs); + screen.currentWorkspaceSig().attach(m_rebuildObs); + // no title for this menu, it should be a submenu in the window menu. + disableTitle(); + // setup menu items + rebuildMenu(); +} - disableTitle(); - // build menu - update(0); +SendToMenu::~SendToMenu() { + delete m_rebuildObs; } -void SendToMenu::update(FbTk::Subject *subj) { - if (subj != 0) { - if (subj == &(theme().reconfigSig())) { - // we got reconfig Theme signal, let base menu handle it - FbTk::Menu::update(subj); - return; - } - - } +void SendToMenu::rebuildMenu() { // rebuild menu removeAll();@@ -95,6 +93,7 @@ void SendToMenu::show() {
if (WindowCmd<void>::window() != 0) { for (unsigned int i=0; i < numberOfItems(); ++i) setItemEnabled(i, true); + // update the workspace for the current window setItemEnabled(WindowCmd<void>::window()->workspaceNumber(), false); updateMenu(); }
@@ -1,5 +1,5 @@
// SendToMenu.hh for Fluxbox -// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) +// Copyright (c) 2003 - 2008 Henrik Kinnunen (fluxgen at fluxbox dot org) // and Simon Bowden (rathnor at users.sourceforge.net) // // Permission is hereby granted, free of charge, to any person obtaining a@@ -25,15 +25,28 @@ #define SENDTOMENU_HH
#include "FbMenu.hh" +namespace FbTk { +class Observer; +} + class BScreen; +/** + * Creates the "send to menu". + * Displays all the workspaces for which the current window can be sent to. + */ class SendToMenu:public FbMenu { public: - explicit SendToMenu(BScreen &win); - virtual ~SendToMenu() { } + /// @param screen the screen on which this menu should be created on. + explicit SendToMenu(BScreen &screen); + virtual ~SendToMenu(); + /// @see FbTk::Menu void show(); -protected: - void update(FbTk::Subject *subj); +private: + /// Rebuild the menu from scratch. + void rebuildMenu(); + /// listens to signals that makes this instance need to rebuild menu + FbTk::Observer *m_rebuildObs; }; #endif // SENDTOMENU_HH
@@ -30,6 +30,7 @@ #include "fluxbox.hh"
#include "WinClient.hh" #include "Screen.hh" #include "ButtonTheme.hh" +#include "SimpleObserver.hh" #include <X11/Xutil.h> #include <X11/Xatom.h>@@ -166,8 +167,10 @@ m_selection_owner(m_window, 0, 0, 1, 1, SubstructureNotifyMask, false, false, CopyFromParent, InputOnly) {
FbTk::EventManager::instance()->add(*this, m_window); FbTk::EventManager::instance()->add(*this, m_selection_owner); - m_theme->reconfigSig().attach(this); - screen.bgChangeSig().attach(this); + // setup signals + m_observer.reset(makeObserver(*this, &SystemTray::update)); + m_theme->reconfigSig().attach(m_observer.get()); + screen.bgChangeSig().attach(m_observer.get()); Fluxbox* fluxbox = Fluxbox::instance(); Display *disp = fluxbox->display();@@ -216,7 +219,7 @@ ce.xclient.data.l[4] = 0l; // selection specific data
XSendEvent(disp, root_window, false, StructureNotifyMask, &ce); - update(0); + update(); } SystemTray::~SystemTray() {@@ -276,7 +279,7 @@ }
void SystemTray::show() { - update(0); + update(); m_window.show(); }@@ -470,7 +473,7 @@ FbTk::translateSize(orientation(), w_rot0, h_rot0);
unsigned int trayw = m_num_visible_clients*h_rot0 + bw, trayh = h_rot0; FbTk::translateSize(orientation(), trayw, trayh); resize(trayw, trayh); - update(0); + update(); // move and resize clients ClientList::iterator client_it = m_clients.begin();@@ -529,7 +532,7 @@ m_num_visible_clients++;
rearrangeClients(); } -void SystemTray::update(FbTk::Subject* subject) { +void SystemTray::update() { if (!m_theme->texture().usePixmap()) { m_window.setBackgroundColor(m_theme->texture().color());
@@ -25,12 +25,12 @@
#include "FbTk/FbWindow.hh" #include "FbTk/EventHandler.hh" -#include "FbTk/Observer.hh" #include "ToolTheme.hh" #include "ToolbarItem.hh" #include <list> +#include <memory> class BScreen; class ButtonTheme;@@ -39,9 +39,10 @@ class AtomHandler;
namespace FbTk { template <class T> class ThemeProxy; +class Observer; } -class SystemTray: public ToolbarItem, public FbTk::EventHandler, public FbTk::Observer { +class SystemTray: public ToolbarItem, public FbTk::EventHandler { public: explicit SystemTray(const FbTk::FbWindow &parent,@@ -75,7 +76,7 @@ void renderTheme(unsigned char alpha) {
m_window.setBorderWidth(m_theme->border().width()); m_window.setBorderColor(m_theme->border().color()); m_window.setAlpha(alpha); - update(0); + update(); } void updateSizing() { m_window.setBorderWidth(m_theme->border().width()); }@@ -85,7 +86,7 @@ static Atom getXEmbedInfoAtom();
private: - void update(FbTk::Subject *subj); + void update(); typedef std::list<TrayWindow *> ClientList; ClientList::iterator findClient(Window win);@@ -108,7 +109,7 @@
// gaim/pidgin seems to barf if the selection is not an independent window. // I suspect it's an interacton with parent relationship and gdk window caching. FbTk::FbWindow m_selection_owner; - + std::auto_ptr<FbTk::Observer> m_observer; }; #endif // SYSTEMTRAY_HH
@@ -50,7 +50,7 @@ #include "FbTk/Transparent.hh"
#include "FbTk/BoolMenuItem.hh" #include "FbTk/IntMenuItem.hh" #include "FbTk/Shape.hh" - +#include "FbTk/SimpleObserver.hh" // use GNU extensions #ifndef _GNU_SOURCE@@ -240,11 +240,15 @@ scrn.name() + ".toolbar.tools", scrn.altName() + ".Toolbar.Tools"),
m_shape(new FbTk::Shape(frame.window, 0)), m_resize_lock(false) { _FB_USES_NLS; + // NOTE: first subject is always the rearrangeItem ! + m_observers.push_back(makeObserver(*this, &Toolbar::rearrangeItems)); // we need to get notified when the theme is reloaded - m_theme.reconfigSig().attach(this); + m_observers.push_back(makeObserver(*this, &Toolbar::reconfigure)); + m_theme.reconfigSig().attach(m_observers.back()); + screen().reconfigureSig().attach(m_observers.back()); // get this on antialias change // listen to screen size changes - screen().resizeSig().attach(this); - screen().reconfigureSig().attach(this); // get this on antialias change + screen().resizeSig().attach(m_observers.back()); + moveToLayer((*m_rc_layernum).getNum());@@ -370,6 +374,7 @@ m_layeritem.lower();
} void Toolbar::reconfigure() { + updateVisibleState(); if (!doAutoHide() && isHidden())@@ -426,7 +431,8 @@ ToolbarItem *item = m_tool_factory.create(*item_it, frame.window, *this);
if (item == 0) continue; m_item_list.push_back(item); - item->resizeSig().attach(this); + // attach to first observer ( which must be rearrangeItems ) + item->resizeSig().attach(m_observers[0]); } // show all items@@ -515,6 +521,11 @@ // we're done with all resizing and stuff now we can request a new
// area to be reserved on screen updateStrut(); +#ifdef XINERAMA + if (m_xineramaheadmenu) + m_xineramaheadmenu->reloadHeads(); +#endif // XINERAMA + }@@ -611,22 +622,6 @@ event.xconfigure.window != window().window()) {
rearrangeItems(); } */ -} - -void Toolbar::update(FbTk::Subject *subj) { - - // either screen reconfigured, theme was reloaded - // or a tool resized itself - - if (typeid(*subj) == typeid(ToolbarItem::ToolbarItemSubject)) - rearrangeItems(); - else - reconfigure(); - -#ifdef XINERAMA - if (subj == &m_screen.resizeSig() && m_xineramaheadmenu) - m_xineramaheadmenu->reloadHeads(); -#endif // XINERAMA } void Toolbar::setPlacement(Toolbar::Placement where) {
@@ -37,7 +37,6 @@ #endif // XINERAMA
#include "FbTk/Timer.hh" #include "FbTk/Resource.hh" -#include "FbTk/Observer.hh" #include "FbTk/XLayer.hh" #include "FbTk/XLayerItem.hh" #include "FbTk/EventHandler.hh"@@ -57,7 +56,8 @@ }
/// The toolbar. /// Handles iconbar, workspace name view and clock view -class Toolbar: public FbTk::EventHandler, public FbTk::Observer, public LayerObject { +class Toolbar: public FbTk::EventHandler, + public LayerObject { public: /// Toolbar placement on the screen@@ -98,8 +98,6 @@ //@}
void reconfigure(); void setPlacement(Placement where); - - void update(FbTk::Subject *subj); int layerNumber() const { return const_cast<FbTk::XLayerItem &>(m_layeritem).getLayerNum(); }@@ -193,6 +191,8 @@ typedef std::list<std::string> StringList;
StringList m_tools; bool m_resize_lock; ///< to lock rearrangeItems or not + /// observers for various signals + std::vector<FbTk::Observer*> m_observers; };