From 797038823815f446c25d191837e63a022209641d Mon Sep 17 00:00:00 2001
From: Mark Tiefenbruck <mark@fluxbox.org>
Date: Sun, 3 Aug 2008 21:59:14 -0700
Subject: add selection box to various "choose one of these" menu items

---
 ChangeLog                        |  3 ++
 nls/C/Translation.m              |  2 +-
 nls/en_GB/Translation.m          |  2 +-
 nls/en_GB/generated-ISO-8859-1.m |  2 +-
 nls/en_GB/generated-UTF-8.m      |  2 +-
 nls/en_US/Translation.m          |  2 +-
 nls/en_US/generated-ISO-8859-1.m |  2 +-
 nls/en_US/generated-UTF-8.m      |  2 +-
 src/FbTk/RadioMenuItem.hh        | 63 ++++++++++++++++++++++++++++++++++++++++
 src/FocusModelMenuItem.hh        | 18 ++++++------
 src/IconbarTool.cc               | 18 ++++++------
 src/LayerMenu.hh                 | 12 ++++----
 src/Screen.cc                    |  9 +++---
 src/Slit.cc                      | 11 +++----
 src/StyleMenuItem.cc             |  2 +-
 src/StyleMenuItem.hh             |  4 +--
 src/Toolbar.cc                   | 25 +++++++++-------
 src/Xinerama.hh                  | 12 ++++----
 18 files changed, 132 insertions(+), 59 deletions(-)
 create mode 100644 src/FbTk/RadioMenuItem.hh

diff --git a/ChangeLog b/ChangeLog
index cdd5390..9ea83cd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,9 @@
  (Format: Year/Month/Day)
 Changes for 1.1
 *08/08/04:
+   * Add selection box to various "choose one of these" menu items (Mark)
+     Toolbar.cc Slit.cc Screen.cc LayerMenu.hh Xinerama.hh StyleMenuItem.cc/hh
+     added FbTk/RadioMenuItem.hh
    * Add window list argument to ArrangeWindows (Mark)
      WorkspaceCmd.cc/hh
 *08/06/26:
diff --git a/nls/C/Translation.m b/nls/C/Translation.m
index 8f05dbf..16a8bb7 100644
--- a/nls/C/Translation.m
+++ b/nls/C/Translation.m
@@ -170,7 +170,7 @@ $set 13 #Slit
 1 Clients
 2 Cycle Down
 3 Cycle Up
-4 Slit Direction
+4 Slit Direction:
 5 Slit Layer
 6 Slit on Head
 7 Slit Placement
diff --git a/nls/en_GB/Translation.m b/nls/en_GB/Translation.m
index 8f05dbf..16a8bb7 100644
--- a/nls/en_GB/Translation.m
+++ b/nls/en_GB/Translation.m
@@ -170,7 +170,7 @@ $set 13 #Slit
 1 Clients
 2 Cycle Down
 3 Cycle Up
-4 Slit Direction
+4 Slit Direction:
 5 Slit Layer
 6 Slit on Head
 7 Slit Placement
diff --git a/nls/en_GB/generated-ISO-8859-1.m b/nls/en_GB/generated-ISO-8859-1.m
index 8f05dbf..16a8bb7 100644
--- a/nls/en_GB/generated-ISO-8859-1.m
+++ b/nls/en_GB/generated-ISO-8859-1.m
@@ -170,7 +170,7 @@ $set 13 #Slit
 1 Clients
 2 Cycle Down
 3 Cycle Up
-4 Slit Direction
+4 Slit Direction:
 5 Slit Layer
 6 Slit on Head
 7 Slit Placement
diff --git a/nls/en_GB/generated-UTF-8.m b/nls/en_GB/generated-UTF-8.m
index 1f20fa4..9d48dfe 100644
--- a/nls/en_GB/generated-UTF-8.m
+++ b/nls/en_GB/generated-UTF-8.m
@@ -170,7 +170,7 @@ $set 13 #Slit
 1 Clients
 2 Cycle Down
 3 Cycle Up
-4 Slit Direction
+4 Slit Direction:
 5 Slit Layer
 6 Slit on Head
 7 Slit Placement
diff --git a/nls/en_US/Translation.m b/nls/en_US/Translation.m
index 8f05dbf..16a8bb7 100644
--- a/nls/en_US/Translation.m
+++ b/nls/en_US/Translation.m
@@ -170,7 +170,7 @@ $set 13 #Slit
 1 Clients
 2 Cycle Down
 3 Cycle Up
-4 Slit Direction
+4 Slit Direction:
 5 Slit Layer
 6 Slit on Head
 7 Slit Placement
diff --git a/nls/en_US/generated-ISO-8859-1.m b/nls/en_US/generated-ISO-8859-1.m
index 8f05dbf..16a8bb7 100644
--- a/nls/en_US/generated-ISO-8859-1.m
+++ b/nls/en_US/generated-ISO-8859-1.m
@@ -170,7 +170,7 @@ $set 13 #Slit
 1 Clients
 2 Cycle Down
 3 Cycle Up
-4 Slit Direction
+4 Slit Direction:
 5 Slit Layer
 6 Slit on Head
 7 Slit Placement
diff --git a/nls/en_US/generated-UTF-8.m b/nls/en_US/generated-UTF-8.m
index 1f20fa4..9d48dfe 100644
--- a/nls/en_US/generated-UTF-8.m
+++ b/nls/en_US/generated-UTF-8.m
@@ -170,7 +170,7 @@ $set 13 #Slit
 1 Clients
 2 Cycle Down
 3 Cycle Up
-4 Slit Direction
+4 Slit Direction:
 5 Slit Layer
 6 Slit on Head
 7 Slit Placement
diff --git a/src/FbTk/RadioMenuItem.hh b/src/FbTk/RadioMenuItem.hh
new file mode 100644
index 0000000..ddd2274
--- /dev/null
+++ b/src/FbTk/RadioMenuItem.hh
@@ -0,0 +1,63 @@
+// RadioMenuItem.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.
+
+#ifndef FBTK_RADIOMENUITEM_HH
+#define FBTK_RADIOMENUITEM_HH
+
+#include "MenuItem.hh"
+
+namespace FbTk {
+
+class RadioMenuItem: public MenuItem {
+public:
+    RadioMenuItem(): MenuItem() { setToggleItem(true); }
+
+    explicit RadioMenuItem(const FbString &label):
+        MenuItem(label) {
+        setToggleItem(true);
+    }
+
+    RadioMenuItem(const FbString &label, Menu &host_menu):
+        MenuItem(label, host_menu) {
+        setToggleItem(true);
+    }
+
+    /// create a menu item with a specific command to be executed on click
+    RadioMenuItem(const FbString &label, RefCount<Command<void> > &cmd,
+                  Menu *menu = 0):
+        MenuItem(label, cmd, menu) {
+        setToggleItem(true);
+    }
+
+    RadioMenuItem(const FbString &label, Menu *submenu, Menu *host_menu = 0):
+        MenuItem(label, submenu, host_menu) {
+        setToggleItem(true);
+    }
+
+    virtual ~RadioMenuItem() { }
+
+    virtual bool isSelected() const = 0;
+    bool isEnabled() const { return !isSelected(); }
+};
+
+} // end namespace FbTk
+
+#endif // FBTK_RADIOMENUITEM_HH
diff --git a/src/FocusModelMenuItem.hh b/src/FocusModelMenuItem.hh
index d75e8a0..7541659 100644
--- a/src/FocusModelMenuItem.hh
+++ b/src/FocusModelMenuItem.hh
@@ -24,7 +24,7 @@
 #define FOCUSMODELMENUITEM_HH
 
 
-#include "FbTk/MenuItem.hh"
+#include "FbTk/RadioMenuItem.hh"
 #include "FbTk/RefCount.hh"
 
 namespace FbTk {
@@ -33,22 +33,22 @@ template <class T> class Command;
 
 #include "FocusControl.hh"
 
-class FocusModelMenuItem : public FbTk::MenuItem {
+class FocusModelMenuItem : public FbTk::RadioMenuItem {
 public:
     FocusModelMenuItem(const FbTk::FbString &label, FocusControl &focus_control, 
                        FocusControl::FocusModel model,
                        FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label, cmd), 
+        FbTk::RadioMenuItem(label, cmd),
         m_focus_control(focus_control), 
         m_focusmodel(model) {
         setCloseOnClick(false);
     }
 
-    bool isEnabled() const { return m_focus_control.focusModel() != m_focusmodel; }
+    bool isSelected() const { return m_focus_control.focusModel() == m_focusmodel; }
 
     void click(int button, int time, unsigned int mods) {
         m_focus_control.setFocusModel(m_focusmodel);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
 
 private:
@@ -56,23 +56,23 @@ private:
     FocusControl::FocusModel m_focusmodel;
 };
 
-class TabFocusModelMenuItem : public FbTk::MenuItem {
+class TabFocusModelMenuItem : public FbTk::RadioMenuItem {
 public:
     TabFocusModelMenuItem(const FbTk::FbString &label, 
                           FocusControl &focus_control,
                           FocusControl::TabFocusModel model, 
                           FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label, cmd), 
+        FbTk::RadioMenuItem(label, cmd),
         m_focus_control(focus_control), 
         m_tabfocusmodel(model) {
         setCloseOnClick(false);
     }
 
-    bool isEnabled() const { return m_focus_control.tabFocusModel() != m_tabfocusmodel; }
+    bool isSelected() const { return m_focus_control.tabFocusModel() == m_tabfocusmodel; }
 
     void click(int button, int time, unsigned int mods) {
         m_focus_control.setTabFocusModel(m_tabfocusmodel);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
 
 private:
diff --git a/src/IconbarTool.cc b/src/IconbarTool.cc
index b6e2900..f2ed082 100644
--- a/src/IconbarTool.cc
+++ b/src/IconbarTool.cc
@@ -39,7 +39,7 @@
 #include "FbTk/STLUtil.hh"
 #include "FbTk/I18n.hh"
 #include "FbTk/Menu.hh"
-#include "FbTk/MenuItem.hh"
+#include "FbTk/RadioMenuItem.hh"
 #include "FbTk/BoolMenuItem.hh"
 #include "FbTk/RefCount.hh"
 #include "FbTk/SimpleCommand.hh"
@@ -99,18 +99,18 @@ void FbTk::Resource<FbTk::Container::Alignment>::setFromString(const char *str)
 
 namespace {
 
-class ToolbarModeMenuItem : public FbTk::MenuItem {
+class ToolbarModeMenuItem : public FbTk::RadioMenuItem {
 public:
     ToolbarModeMenuItem(const FbTk::FbString &label, IconbarTool &handler,
                         string mode,
                         FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label, cmd), m_handler(handler), m_mode(mode) {
+        FbTk::RadioMenuItem(label, cmd), m_handler(handler), m_mode(mode) {
         setCloseOnClick(false);
     }
-    bool isEnabled() const { return m_handler.mode() != m_mode; }
+    bool isSelected() const { return m_handler.mode() == m_mode; }
     void click(int button, int time, unsigned int mods) {
         m_handler.setMode(m_mode);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
 
 private:
@@ -118,18 +118,18 @@ private:
     string m_mode;
 };
 
-class ToolbarAlignMenuItem: public FbTk::MenuItem {
+class ToolbarAlignMenuItem: public FbTk::RadioMenuItem {
 public:
     ToolbarAlignMenuItem(const FbTk::FbString &label, IconbarTool &handler,
                         FbTk::Container::Alignment mode,
                         FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label, cmd), m_handler(handler), m_mode(mode) {
+        FbTk::RadioMenuItem(label, cmd), m_handler(handler), m_mode(mode) {
         setCloseOnClick(false);
     }
-    bool isEnabled() const { return m_handler.alignment() != m_mode; }
+    bool isSelected() const { return m_handler.alignment() == m_mode; }
     void click(int button, int time, unsigned int mods) {
         m_handler.setAlignment(m_mode);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
 
 private:
diff --git a/src/LayerMenu.hh b/src/LayerMenu.hh
index 8de0eba..40e934c 100644
--- a/src/LayerMenu.hh
+++ b/src/LayerMenu.hh
@@ -26,7 +26,7 @@
 
 #include "ToggleMenu.hh"
 
-#include "FbTk/MenuItem.hh"
+#include "FbTk/RadioMenuItem.hh"
 
 class LayerObject {
 public:
@@ -37,20 +37,20 @@ public:
 
 
 /// this class holds the layermenu items
-class LayerMenuItem : public FbTk::MenuItem {
+class LayerMenuItem : public FbTk::RadioMenuItem {
 public:
     LayerMenuItem(const FbTk::FbString &label, LayerObject *object,
                   int layernum, FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label, cmd), m_object(object), m_layernum(layernum) {}
+        FbTk::RadioMenuItem(label, cmd), m_object(object), m_layernum(layernum) {}
 
     LayerMenuItem(const FbTk::FbString &label, LayerObject *object,
                   int layernum):
-        FbTk::MenuItem(label), m_object(object), m_layernum(layernum) {}
+        FbTk::RadioMenuItem(label), m_object(object), m_layernum(layernum) {}
 
-    bool isEnabled() const { return m_object->layerNumber() != m_layernum; }
+    bool isSelected() const { return m_object->layerNumber() == m_layernum; }
     void click(int button, int time, unsigned int mods) {
         m_object->moveToLayer(m_layernum);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
     
 private:
diff --git a/src/Screen.cc b/src/Screen.cc
index 658252b..838a313 100644
--- a/src/Screen.cc
+++ b/src/Screen.cc
@@ -38,6 +38,7 @@
 #include "FbTk/BoolMenuItem.hh"
 #include "FbTk/IntMenuItem.hh"
 #include "FocusModelMenuItem.hh"
+#include "RadioMenuItem.hh"
 
 // menus
 #include "FbMenu.hh"
@@ -174,21 +175,21 @@ int anotherWMRunning(Display *display, XErrorEvent *) {
 }
 
 
-class TabPlacementMenuItem: public FbTk::MenuItem {
+class TabPlacementMenuItem: public FbTk::RadioMenuItem {
 public:
     TabPlacementMenuItem(FbTk::FbString & label, BScreen &screen,
                          FbWinFrame::TabPlacement place,
                          FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label, cmd),
+        FbTk::RadioMenuItem(label, cmd),
         m_screen(screen),
         m_place(place) {
         setCloseOnClick(false);
     }
 
-    bool isEnabled() const { return m_screen.getTabPlacement() != m_place; }
+    bool isSelected() const { return m_screen.getTabPlacement() == m_place; }
     void click(int button, int time, unsigned int mods) {
         m_screen.saveTabPlacement(m_place);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
 
 
diff --git a/src/Slit.cc b/src/Slit.cc
index ecd8280..20b86d6 100644
--- a/src/Slit.cc
+++ b/src/Slit.cc
@@ -57,6 +57,7 @@
 #include "FbTk/I18n.hh"
 #include "FbTk/BoolMenuItem.hh"
 #include "FbTk/IntMenuItem.hh"
+#include "FbTk/RadioMenuItem.hh"
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/types.h>
@@ -236,16 +237,16 @@ private:
     string m_label;
 };
 
-class PlaceSlitMenuItem: public FbTk::MenuItem {
+class PlaceSlitMenuItem: public FbTk::RadioMenuItem {
 public:
     PlaceSlitMenuItem(const FbTk::FbString &label, Slit &slit, Slit::Placement place, FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label, cmd), m_slit(slit), m_place(place) {
+        FbTk::RadioMenuItem(label, cmd), m_slit(slit), m_place(place) {
         setCloseOnClick(false);
     }
-    bool isEnabled() const { return m_slit.placement() != m_place; }
+    bool isSelected() const { return m_slit.placement() == m_place; }
     void click(int button, int time, unsigned int mods) {
         m_slit.setPlacement(m_place);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
 private:
     Slit &m_slit;
@@ -1291,7 +1292,7 @@ void Slit::setupMenu() {
 
     m_slitmenu.insert(alpha_menuitem);
 
-    m_slitmenu.insert(new SlitDirMenuItem(_FB_XTEXT(Slit, Direction, "Slit Direction", "Orientation of slit"),
+    m_slitmenu.insert(new SlitDirMenuItem(_FB_XTEXT(Slit, Direction, "Slit Direction:", "Orientation of slit"),
                                           *this,
                                           save_and_reconfigure));
     m_slitmenu.insert(_FB_XTEXT(Slit, ClientsMenu, "Clients", "Slit client menu"), &m_clientlist_menu);
diff --git a/src/StyleMenuItem.cc b/src/StyleMenuItem.cc
index 628935d..8e557a7 100644
--- a/src/StyleMenuItem.cc
+++ b/src/StyleMenuItem.cc
@@ -28,7 +28,7 @@
 #include "FbTk/StringUtil.hh"
 
 StyleMenuItem::StyleMenuItem(const FbTk::FbString &label, const std::string &filename):
-    FbTk::MenuItem(label), 
+    FbTk::RadioMenuItem(label), 
     m_filename(filename) {
     // perform shell style ~ home directory expansion
     // and insert style      
diff --git a/src/StyleMenuItem.hh b/src/StyleMenuItem.hh
index d918432..3c0c8ac 100644
--- a/src/StyleMenuItem.hh
+++ b/src/StyleMenuItem.hh
@@ -23,9 +23,9 @@
 #ifndef STYLEMENUITEM_HH
 #define STYLEMENUITEM_HH
 
-#include "FbTk/MenuItem.hh"
+#include "FbTk/RadioMenuItem.hh"
 
-class StyleMenuItem: public FbTk::MenuItem {
+class StyleMenuItem: public FbTk::RadioMenuItem {
 public:
     StyleMenuItem(const FbTk::FbString &label, const std::string &filename);
     bool isSelected() const;
diff --git a/src/Toolbar.cc b/src/Toolbar.cc
index 540ceb9..440eff5 100644
--- a/src/Toolbar.cc
+++ b/src/Toolbar.cc
@@ -156,16 +156,22 @@ getString() const {
 } // end namespace FbTk
 
 namespace {
-class SetToolbarPlacementCmd: public FbTk::Command<void> {
+
+class PlaceToolbarMenuItem: public FbTk::RadioMenuItem {
 public:
-    SetToolbarPlacementCmd(Toolbar &tbar, Toolbar::Placement place):m_tbar(tbar), m_place(place) { }
-    void execute() {
-        m_tbar.setPlacement(m_place);
-        m_tbar.reconfigure();
+    PlaceToolbarMenuItem(const FbTk::FbString &label, Toolbar &toolbar,
+        Toolbar::Placement place):
+        FbTk::RadioMenuItem(label), m_toolbar(toolbar), m_place(place) {
+        setCloseOnClick(false);
+    }
+    bool isSelected() const { return m_toolbar.placement() == m_place; }
+    void click(int button, int time, unsigned int mods) {
+        m_toolbar.setPlacement(m_place);
+        m_toolbar.reconfigure();
         Fluxbox::instance()->save_rc();
     }
 private:
-    Toolbar &m_tbar;
+    Toolbar &m_toolbar;
     Toolbar::Placement m_place;
 };
 
@@ -909,11 +915,10 @@ void Toolbar::setupMenus(bool skip_new_placement) {
             if (str == "") {
                 placementMenu().insert("");
                 placementMenu().setItemEnabled(i, false);
-            } else {
-                RefCommand setplace(new SetToolbarPlacementCmd(*this, placement));
-                placementMenu().insert(str, setplace);
+            } else
+                placementMenu().insert(new PlaceToolbarMenuItem(str, *this,
+                                                                placement));
 
-            }
             place_menu.pop_front();
         }
     }
diff --git a/src/Xinerama.hh b/src/Xinerama.hh
index eab2e37..876005f 100644
--- a/src/Xinerama.hh
+++ b/src/Xinerama.hh
@@ -29,7 +29,7 @@
 
 #include "FbTk/RefCount.hh"
 #include "FbTk/SimpleCommand.hh"
-#include "FbTk/MenuItem.hh"
+#include "FbTk/RadioMenuItem.hh"
 
 // provides a generic way for giving an object a xinerama head menu
 // The object must have two functions:
@@ -38,18 +38,18 @@
 
 /// this class holds the xinerama items
 template <typename ItemType> 
-class XineramaHeadMenuItem : public FbTk::MenuItem {
+class XineramaHeadMenuItem : public FbTk::RadioMenuItem {
 public:
     XineramaHeadMenuItem(const FbTk::FbString &label, ItemType &object, int headnum,
                   FbTk::RefCount<FbTk::Command<void> > &cmd):
-        FbTk::MenuItem(label,cmd), m_object(object), m_headnum(headnum) {}
+        FbTk::RadioMenuItem(label,cmd), m_object(object), m_headnum(headnum) {}
     XineramaHeadMenuItem(const FbTk::FbString &label, ItemType &object, int headnum):
-        FbTk::MenuItem(label), m_object(object), m_headnum(headnum) {}
+        FbTk::RadioMenuItem(label), m_object(object), m_headnum(headnum) {}
 
-    bool isEnabled() const { return m_object.getOnHead() != m_headnum; } 
+    bool isSelected() const { return m_object.getOnHead() == m_headnum; } 
     void click(int button, int time, unsigned int mods) {
         m_object.saveOnHead(m_headnum);
-        FbTk::MenuItem::click(button, time, mods);
+        FbTk::RadioMenuItem::click(button, time, mods);
     }
     
 private:
-- 
cgit v0.11.2