From 925f968a6af7765f3a37e54eb80483fb87e74449 Mon Sep 17 00:00:00 2001 From: fluxgen <fluxgen> Date: Mon, 8 Sep 2003 17:52:34 +0000 Subject: add iconbar mode --- src/IconbarTool.cc | 400 ++++++++++++++++++++++++++++++++++++++++++++--------- src/IconbarTool.hh | 34 ++++- 2 files changed, 363 insertions(+), 71 deletions(-) diff --git a/src/IconbarTool.cc b/src/IconbarTool.cc index f7f9954..fcaac39 100644 --- a/src/IconbarTool.cc +++ b/src/IconbarTool.cc @@ -20,31 +20,177 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: IconbarTool.cc,v 1.9 2003/08/18 11:13:32 fluxgen Exp $ +// $Id: IconbarTool.cc,v 1.10 2003/09/08 17:52:34 fluxgen Exp $ #include "IconbarTool.hh" #include "Screen.hh" -#include "ImageControl.hh" #include "IconbarTheme.hh" #include "Window.hh" #include "IconButton.hh" #include "Workspace.hh" +#include "fluxbox.hh" + + +#include "FbTk/Menu.hh" +#include "FbTk/MenuItem.hh" +#include "FbTk/RefCount.hh" +#include "FbTk/SimpleCommand.hh" +#include "FbTk/ImageControl.hh" #include <typeinfo> +#include <string> +#include <iterator> +#include <iostream> +using namespace std; + +template<> +void FbTk::Resource<IconbarTool::Mode>::setFromString(const char *strval) { + if (strcasecmp(strval, "None") == 0) + m_value = IconbarTool::NONE; + else if (strcasecmp(strval, "Icons") == 0) + m_value = IconbarTool::ICONS; + else if (strcasecmp(strval, "WorkspaceIcons") == 0) + m_value = IconbarTool::WORKSPACEICONS; + else if (strcasecmp(strval, "Workspace") == 0) + m_value = IconbarTool::WORKSPACE; + else if (strcasecmp(strval, "AllWindows") == 0) + m_value = IconbarTool::ALLWINDOWS; + else + setDefaultValue(); +} + + +template<> +string FbTk::Resource<IconbarTool::Mode>::getString() { + + switch (m_value) { + case IconbarTool::NONE: + return string("None"); + break; + case IconbarTool::ICONS: + return string("Icons"); + break; + case IconbarTool::WORKSPACEICONS: + return string("WorkspaceIcons"); + break; + case IconbarTool::WORKSPACE: + return string("Workspace"); + break; + case IconbarTool::ALLWINDOWS: + return string("AllWindows"); + break; + } + // default string + return string("Icons"); +} + +namespace { + +class ToolbarModeMenuItem : public FbTk::MenuItem { +public: + ToolbarModeMenuItem(const char *label, IconbarTool &handler, + IconbarTool::Mode mode, + FbTk::RefCount<FbTk::Command> &cmd): + FbTk::MenuItem(label, cmd), m_handler(handler), m_mode(mode) { + } + bool isEnabled() const { return m_handler.mode() != m_mode; } + void click(int button, int time) { + m_handler.setMode(m_mode); + FbTk::MenuItem::click(button, time); + } + +private: + IconbarTool &m_handler; + IconbarTool::Mode m_mode; +}; + +void setupModeMenu(FbTk::Menu &menu, IconbarTool &handler) { + using namespace FbTk; + + // TODO: nls + menu.setLabel("Iconbar Mode"); + + RefCount<Command> saverc_cmd(new SimpleCommand<Fluxbox>( + *Fluxbox::instance(), + &Fluxbox::save_rc)); + + //TODO: nls + menu.insert(new ToolbarModeMenuItem("None", handler, + IconbarTool::NONE, saverc_cmd)); + menu.insert(new ToolbarModeMenuItem("Icons", handler, + IconbarTool::ICONS, saverc_cmd)); + menu.insert(new ToolbarModeMenuItem("Workspace Icons", handler, + IconbarTool::WORKSPACEICONS, saverc_cmd)); + menu.insert(new ToolbarModeMenuItem("Workspace", handler, + IconbarTool::WORKSPACE, saverc_cmd)); + menu.insert(new ToolbarModeMenuItem("All Windows", handler, + IconbarTool::ALLWINDOWS, saverc_cmd)); + menu.update(); +} + +inline bool checkAddWindow(IconbarTool::Mode mode, const FluxboxWindow &win) { + + // just add the icons that are on the this workspace + switch (mode) { + case IconbarTool::NONE: + break; + case IconbarTool::ICONS: + if (win.isIconic()) + return true; + break; + case IconbarTool::WORKSPACEICONS: + if(win.workspaceNumber() == win.screen().currentWorkspaceID() && + win.isIconic()) + return true; + break; + case IconbarTool::WORKSPACE: + if (win.workspaceNumber() == win.screen().currentWorkspaceID()) + return true; + break; + case IconbarTool::ALLWINDOWS: + return true; + break; + } + + return false; +} + +void removeDuplicate(const IconbarTool::IconList &iconlist, std::list<FluxboxWindow *> &windowlist) { + IconbarTool::IconList::const_iterator win_it = iconlist.begin(); + IconbarTool::IconList::const_iterator win_it_end = iconlist.end(); + std::list<FluxboxWindow *>::iterator remove_it = windowlist.end(); + for (; win_it != win_it_end; ++win_it) + remove_it = remove(windowlist.begin(), remove_it, &(*win_it)->win()); + + // remove already existing windows + windowlist.erase(remove_it, windowlist.end()); + +} + +}; // end anonymous namespace -IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, BScreen &screen): +IconbarTool::IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, BScreen &screen, + FbTk::Menu &menu): ToolbarItem(ToolbarItem::RELATIVE), m_screen(screen), m_icon_container(parent), m_theme(theme), m_focused_pm(0), m_unfocused_pm(0), - m_empty_pm(0) { + m_empty_pm(0), + m_rc_mode(screen.resourceManager(), WORKSPACE, + screen.name() + ".iconbar.mode", screen.altName() + ".Iconbar.Mode"), + m_menu(*screen.menuTheme(), menu.screenNumber(), screen.imageControl()) { + + // setup menu + setupModeMenu(m_menu, *this); + menu.insert(m_menu.label().c_str(), &m_menu); // setup signals theme.reconfigSig().attach(this); screen.clientListSig().attach(this); + screen.iconListSig().attach(this); screen.currentWorkspaceSig().attach(this); update(0); @@ -88,6 +234,41 @@ void IconbarTool::hide() { m_icon_container.hide(); } +void IconbarTool::setMode(Mode mode) { + if (mode == *m_rc_mode) + return; + + *m_rc_mode = mode; + + // lock graphics update + m_icon_container.setUpdateLock(true); + + deleteIcons(); + + // update mode + switch (*m_rc_mode) { + case NONE: + break; + case ICONS: + case WORKSPACEICONS: + updateIcons(); + break; + case WORKSPACE: + updateWorkspace(); + break; + case ALLWINDOWS: + updateAllWindows(); + break; + }; + + // unlock graphics update + m_icon_container.setUpdateLock(false); + m_icon_container.update(); + m_icon_container.showSubwindows(); + + renderTheme(); +} + unsigned int IconbarTool::width() const { return m_icon_container.width(); } @@ -105,7 +286,14 @@ void IconbarTool::update(FbTk::Subject *subj) { if (m_screen.isShuttingdown()) return; - // just focus signal? + if (mode() == NONE) { + if (typeid(*subj) == typeid(FbTk::Theme)) + renderTheme(); + + return; + } + + // handle window signal if (subj != 0 && typeid(*subj) == typeid(FluxboxWindow::WinSubject)) { // we handle everything except die signal here FluxboxWindow::WinSubject *winsubj = static_cast<FluxboxWindow::WinSubject *>(subj); @@ -113,83 +301,80 @@ void IconbarTool::update(FbTk::Subject *subj) { renderWindow(winsubj->win()); return; } else if (subj == &(winsubj->win().workspaceSig())) { + // we can ignore this signal if we're in ALLWINDOWS mode + if (mode() == ALLWINDOWS) + return; + // workspace changed for this window, and if it's not on current workspace we remove it - if (m_screen.currentWorkspaceID() != winsubj->win().workspaceNumber()) + if (m_screen.currentWorkspaceID() != winsubj->win().workspaceNumber()) { removeWindow(winsubj->win()); + renderTheme(); + } return; - } else { // die sig + } else if (subj == &(winsubj->win().dieSig())) { // die sig removeWindow(winsubj->win()); + renderTheme(); return; // we don't need to update the entire list + } else if (subj == &(winsubj->win().stateSig())) { + if (mode() == ICONS || mode() == WORKSPACEICONS) { + if (!winsubj->win().isIconic()) { + removeWindow(winsubj->win()); + renderTheme(); + } + } else { + if (winsubj->win().isIconic()) { + removeWindow(winsubj->win()); + renderTheme(); + } + } + return; + } else { + // signal not handled + return; } } bool remove_all = false; // if we should readd all windows - if (subj != 0 && typeid(*subj) == typeid(BScreen::ScreenSubject)) { + if (subj != 0 && typeid(*subj) == typeid(BScreen::ScreenSubject) && mode() != ALLWINDOWS) { BScreen::ScreenSubject *screen_subj = static_cast<BScreen::ScreenSubject *>(subj); - if (&screen_subj->screen().currentWorkspaceSig() == screen_subj) { + // current workspace sig + if (&m_screen.currentWorkspaceSig() == screen_subj && + mode() != ALLWINDOWS && mode() != ICONS) { remove_all = true; // remove and readd all windows + } else if (&m_screen.iconListSig() == screen_subj && + (mode() == ALLWINDOWS || mode() == ICONS)) { + remove_all = true; } } - // ok, we got some signal that we need to update our iconbar container - - // get current workspace and all it's clients - Workspace &space = *m_screen.currentWorkspace(); - // build a ItemList and add it (faster than adding single items) - Container::ItemList items; - Workspace::Windows itemlist(space.windowList()); - // add icons to the itemlist - { - BScreen::Icons::iterator icon_it = m_screen.getIconList().begin(); - BScreen::Icons::iterator icon_it_end = m_screen.getIconList().end(); - for (; icon_it != icon_it_end; ++icon_it) { - // just add the icons that are on the this workspace - if ((*icon_it)->workspaceNumber() == m_screen.currentWorkspaceID()) - itemlist.push_back(*icon_it); - } - } - - // go through the current list and see if there're windows to be added - // (note: we dont need to check if there's one deleted since we're listening - // to dieSig ) - if (!remove_all) { - IconList::iterator win_it = m_icon_list.begin(); - IconList::iterator win_it_end = m_icon_list.end(); - Workspace::Windows::iterator remove_it = itemlist.end(); - for (; win_it != win_it_end; ++win_it) - remove_it = remove(itemlist.begin(), remove_it, &(*win_it)->win()); - - itemlist.erase(remove_it, itemlist.end()); - // we dont need to do anything - // since we dont have anything to add ... - if (itemlist.size() == 0) - return; + // lock graphic update + m_icon_container.setUpdateLock(true); - } else { + if (remove_all) deleteIcons(); - } - - // ok, now we should have a list of icons that we need to add - Workspace::Windows::iterator it = itemlist.begin(); - Workspace::Windows::iterator it_end = itemlist.end(); - for (; it != it_end; ++it) { - - // we just want windows that has clients - if ((*it)->clientList().size() == 0) - continue; - IconButton *button = new IconButton(m_icon_container, m_theme.focusedText().font(), **it); - items.push_back(button); - m_icon_list.push_back(button); - - (*it)->focusSig().attach(this); - (*it)->dieSig().attach(this); - (*it)->workspaceSig().attach(this); + // ok, we got some signal that we need to update our iconbar container + switch (mode()) { + case NONE: + return; + break; + case ICONS: + case WORKSPACEICONS: + updateIcons(); + break; + case WORKSPACE: + updateWorkspace(); + break; + case ALLWINDOWS: + updateAllWindows(); + break; } + // unlock container and update graphics + m_icon_container.setUpdateLock(false); m_icon_container.showSubwindows(); - m_icon_container.insertItems(items); + m_icon_container.update(); renderTheme(); } @@ -255,8 +440,6 @@ void IconbarTool::renderTheme() { IconList::iterator icon_it_end = m_icon_list.end(); for (; icon_it != icon_it_end; ++icon_it) renderButton(*(*icon_it)); - - } void IconbarTool::renderButton(IconButton &button) { @@ -300,7 +483,6 @@ void IconbarTool::deleteIcons() { } void IconbarTool::removeWindow(FluxboxWindow &win) { - // got window die signal, lets find and remove the window IconList::iterator it = m_icon_list.begin(); IconList::iterator it_end = m_icon_list.end(); @@ -311,10 +493,94 @@ void IconbarTool::removeWindow(FluxboxWindow &win) { // did we find it? if (it == m_icon_list.end()) return; + + win.focusSig().detach(this); + win.dieSig().detach(this); + win.workspaceSig().detach(this); + win.stateSig().detach(this); + // remove from list and render theme again - delete *it; - m_icon_list.erase(it); + IconButton *button = *it; + m_icon_container.removeItem(m_icon_container.find(*it)); - renderTheme(); + m_icon_list.erase(it); + + delete button; + +} + +void IconbarTool::addWindow(FluxboxWindow &win) { + // we just want windows that has clients + if (win.clientList().size() == 0) + return; + + IconButton *button = new IconButton(m_icon_container, m_theme.focusedText().font(), win); + m_icon_container.insertItem(button); + m_icon_list.push_back(button); + + // dont forget to detach signal in removeWindow + win.focusSig().attach(this); + win.dieSig().attach(this); + win.workspaceSig().attach(this); + win.stateSig().attach(this); +} + + +void IconbarTool::updateIcons() { + std::list<FluxboxWindow *> itemlist; + // add icons to the itemlist + BScreen::Icons::iterator icon_it = m_screen.getIconList().begin(); + BScreen::Icons::iterator icon_it_end = m_screen.getIconList().end(); + for (; icon_it != icon_it_end; ++icon_it) { + if (mode() == ICONS) + itemlist.push_back(*icon_it); + else if (mode() == WORKSPACEICONS && (*icon_it)->workspaceNumber() == m_screen.currentWorkspaceID()) + itemlist.push_back(*icon_it); + } + removeDuplicate(m_icon_list, itemlist); + addList(itemlist); } + +void IconbarTool::updateWorkspace() { + std::list<FluxboxWindow *> itemlist; + Workspace &space = *m_screen.currentWorkspace(); + Workspace::Windows::iterator it = space.windowList().begin(); + Workspace::Windows::iterator it_end = space.windowList().end(); + for (; it != it_end; ++it) { + if (checkAddWindow(mode(), **it)) + itemlist.push_back(*it); + } + removeDuplicate(m_icon_list, itemlist); + addList(itemlist); +} + + +void IconbarTool::updateAllWindows() { + std::list<FluxboxWindow *> full_list; + // for each workspace add clients to full list + BScreen::Workspaces::iterator workspace_it = m_screen.getWorkspacesList().begin(); + BScreen::Workspaces::iterator workspace_it_end = m_screen.getWorkspacesList().end(); + for (; workspace_it != workspace_it_end; ++workspace_it) { + full_list.insert(full_list.end(), + (*workspace_it)->windowList().begin(), + (*workspace_it)->windowList().end()); + } + // add icons + full_list.insert(full_list.end(), + m_screen.getIconList().begin(), + m_screen.getIconList().end()); + + removeDuplicate(m_icon_list, full_list); + addList(full_list); +} + +void IconbarTool::addList(std::list<FluxboxWindow *> &winlist) { + // ok, now we should have a list of icons that we need to add + std::list<FluxboxWindow *>::iterator it = winlist.begin(); + std::list<FluxboxWindow *>::iterator it_end = winlist.end(); + for (; it != it_end; ++it) + addWindow(**it); +} + + diff --git a/src/IconbarTool.hh b/src/IconbarTool.hh index 6dc7bfa..a4cbdf2 100644 --- a/src/IconbarTool.hh +++ b/src/IconbarTool.hh @@ -20,7 +20,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -// $Id: IconbarTool.hh,v 1.6 2003/08/18 11:13:32 fluxgen Exp $ +// $Id: IconbarTool.hh,v 1.7 2003/09/08 17:52:34 fluxgen Exp $ #ifndef ICONBARTOOL_HH #define ICONBARTOOL_HH @@ -29,6 +29,8 @@ #include "Container.hh" #include "FbTk/Observer.hh" +#include "FbTk/Resource.hh" +#include "FbTk/Menu.hh" #include <X11/Xlib.h> @@ -41,7 +43,12 @@ class FluxboxWindow; class IconbarTool: public ToolbarItem, public FbTk::Observer { public: - IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, BScreen &screen); + typedef std::list<IconButton *> IconList; + + enum Mode {NONE, ICONS, WORKSPACEICONS, WORKSPACE, ALLWINDOWS}; + + IconbarTool(const FbTk::FbWindow &parent, IconbarTheme &theme, + BScreen &screen, FbTk::Menu &menu); ~IconbarTool(); void move(int x, int y); @@ -52,11 +59,17 @@ public: void update(FbTk::Subject *subj); void show(); void hide(); + + void setMode(Mode mode); + unsigned int width() const; unsigned int height() const; unsigned int borderWidth() const; + Mode mode() const { return *m_rc_mode; } + private: + /// render single button that holds win void renderWindow(FluxboxWindow &win); /// render single button @@ -65,8 +78,18 @@ private: void renderTheme(); /// destroy all icons void deleteIcons(); - /// remove a single window an render theme again + /// remove a single window void removeWindow(FluxboxWindow &win); + /// add a single window + void addWindow(FluxboxWindow &win); + /// add icons to the list + void updateIcons(); + /// add normal windows to the list + void updateWorkspace(); + /// add all windows to the list + void updateAllWindows(); + /// add a list of windows + void addList(std::list<FluxboxWindow *> &winlist); BScreen &m_screen; Container m_icon_container; @@ -75,8 +98,11 @@ private: Pixmap m_focused_pm, m_unfocused_pm; Pixmap m_empty_pm; ///< pixmap for empty container - typedef std::list<IconButton *> IconList; + IconList m_icon_list; + FbTk::Resource<Mode> m_rc_mode; + + FbTk::Menu m_menu; }; #endif // ICONBARTOOL_HH -- cgit v0.11.2