diff --git a/ChangeLog b/ChangeLog index 43eb3e74..8fc149b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2015-11-12 Markus Gans + * Add two new classes FCheckMenuItem and FRadioMenuItem + for menu check marks and menu option marks (bullets) + 2015-11-12 Markus Gans * Improve menu accelerator keys * Shows accelerator keys on the right side of the FMenu. diff --git a/README.md b/README.md index fcdcc90d..08fa5f55 100644 --- a/README.md +++ b/README.md @@ -171,15 +171,19 @@ Class digramm : : ▲ 1: └──┤ FMessageBox ├----: : : │ : └─────────────┘ : : : │ └------------------------------: - : : └───────────────────┐ ┌──────────┐ : - : : │ ┌───┤ FMenuBar │ : - : : ├───┤ └──────────┘ : - : : ┌───────────┐ │ │ ┌───────┐ : - : : │ FMenuList │◄───┘ └───┤ FMenu │ : - : : └─────┬─────┘ └───────┘ : - : : : ┌───────────┐ : - : : └------------------┤ FMenuItem │ : - : : └───────────┘ : + : : └───────────────┐ ┌──────────┐ : + : : │ ┌───┤ FMenuBar │ : + : : ┌───────────┐ └─────┤ └──────────┘ : + : : │ FMenuList │◄──────────┤ ┌───────┐ : + : : └────┬──────┘ └───┤ FMenu │ : + : : : └───────┘ : + : : 1: ┌────────────────┐* : + : : : *┌───────────┐ ┌──┤ FCheckMenuItem ├-┐ : + : : ├--┤ FMenuItem │◄─┤ └────────────────┘ : : + : : : └───────────┘ │ ┌────────────────┐*: : + : : : └──┤ FRadioMenuItem ├-┤ : + : : : └────────────────┘ : : + : : └---------------------------------------┘ : : └---------------------------------------------------┘ : *┌────────┐ :---┤ FPoint │ diff --git a/doc/class-diagram.txt b/doc/class-diagram.txt index 10cd4a25..5dad3a21 100644 --- a/doc/class-diagram.txt +++ b/doc/class-diagram.txt @@ -74,15 +74,19 @@ : : ▲ 1: └──┤ FMessageBox ├----: : : │ : └─────────────┘ : : : │ └------------------------------: - : : └───────────────────┐ ┌──────────┐ : - : : │ ┌───┤ FMenuBar │ : - : : ├───┤ └──────────┘ : - : : ┌───────────┐ │ │ ┌───────┐ : - : : │ FMenuList │◄───┘ └───┤ FMenu │ : - : : └─────┬─────┘ └───────┘ : - : : : ┌───────────┐ : - : : └------------------┤ FMenuItem │ : - : : └───────────┘ : + : : └───────────────┐ ┌──────────┐ : + : : │ ┌───┤ FMenuBar │ : + : : ┌───────────┐ └─────┤ └──────────┘ : + : : │ FMenuList │◄──────────┤ ┌───────┐ : + : : └────┬──────┘ └───┤ FMenu │ : + : : : └───────┘ : + : : 1: ┌────────────────┐* : + : : : *┌───────────┐ ┌──┤ FCheckMenuItem ├-┐ : + : : ├--┤ FMenuItem │◄─┤ └────────────────┘ : : + : : : └───────────┘ │ ┌────────────────┐*: : + : : : └──┤ FRadioMenuItem ├-┤ : + : : : └────────────────┘ : : + : : └---------------------------------------┘ : : └---------------------------------------------------┘ : *┌────────┐ :---┤ FPoint │ diff --git a/src/Makefile.am b/src/Makefile.am index abf0fc30..7177a5f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,6 +26,8 @@ libfinal_la_SOURCES = \ fmenu.cpp \ fmenubar.cpp \ fmenuitem.cpp \ + fradiomenuitem.cpp \ + fcheckmenuitem.cpp \ fmenulist.cpp \ fdialog.cpp \ fwindow.cpp \ @@ -64,6 +66,8 @@ finalcutinclude_HEADERS = \ fmenu.h \ fmenubar.h \ fmenuitem.h \ + fradiomenuitem.h \ + fcheckmenuitem.h \ fmenulist.h \ fmessagebox.h \ fobject.h \ diff --git a/src/Makefile.clang b/src/Makefile.clang index 33483b5f..eae701c6 100644 --- a/src/Makefile.clang +++ b/src/Makefile.clang @@ -7,33 +7,38 @@ VERSION = "0.1.1" MAJOR := $(shell echo ${VERSION} | cut -d. -f1) LIBDIR = /usr/local/lib64 INCLUDEDIR = /usr/local/include/final -INCLUDE_HEADERS = fapp.h \ - fbuttongroup.h \ - fbutton.h \ - fcheckbox.h \ - fswitch.h \ - fdialog.h \ - fevent.h \ - ffiledialog.h \ - final.h \ - flabel.h \ - flineedit.h \ - flistbox.h \ - fmessagebox.h \ - fobject.h \ - foptimove.h \ - fpoint.h \ - fprogressbar.h \ - fradiobutton.h \ - frect.h \ - fscrollbar.h \ - fstatusbar.h \ - fstring.h \ - fterm.h \ - ftextview.h \ - ftogglebutton.h \ - fwidget.h \ - fwindow.h +INCLUDE_HEADERS = \ + fapp.h \ + fbuttongroup.h \ + fbutton.h \ + fcheckbox.h \ + fswitch.h \ + fdialog.h \ + fevent.h \ + ffiledialog.h \ + final.h \ + flabel.h \ + flineedit.h \ + flistbox.h \ + fmenu.h \ + fmenubar.h \ + fradiomenuitem.h \ + fcheckmenuitem.h \ + fmessagebox.h \ + fobject.h \ + foptimove.h \ + fpoint.h \ + fprogressbar.h \ + fradiobutton.h \ + frect.h \ + fscrollbar.h \ + fstatusbar.h \ + fstring.h \ + fterm.h \ + ftextview.h \ + ftogglebutton.h \ + fwidget.h \ + fwindow.h # compiler parameter CXX = clang++ @@ -45,32 +50,39 @@ GPM = -D F_HAVE_LIBGPM VER = -D F_VERSION=$(VERSION) RM = rm -f LIB = libfinal.so -OBJS = fstring.o \ - fpoint.o \ - frect.o \ - fscrollbar.o \ - fprogressbar.o \ - flineedit.o \ - fbutton.o \ - fbuttongroup.o \ - ftogglebutton.o \ - fradiobutton.o \ - fcheckbox.o \ - fswitch.o \ - flabel.o \ - flistbox.o \ - fdialog.o \ - fwindow.o \ - fmessagebox.o \ - ffiledialog.o \ - ftextview.o \ - fstatusbar.o \ - fterm.o \ - fevent.o \ - foptimove.o \ - fapp.o \ - fwidget.o \ - fobject.o +OBJS = \ + fstring.o \ + fpoint.o \ + frect.o \ + fscrollbar.o \ + fprogressbar.o \ + flineedit.o \ + fbutton.o \ + fbuttongroup.o \ + ftogglebutton.o \ + fradiobutton.o \ + fcheckbox.o \ + fswitch.o \ + flabel.o \ + flistbox.o \ + fmenu.o \ + fmenubar.o \ + fmenuitem.o \ + fradiomenuitem.o \ + fcheckmenuitem.o \ + fmenulist.o \ + fdialog.o \ + fwindow.o \ + fmessagebox.o \ + ffiledialog.o \ + ftextview.o \ + fstatusbar.o \ + fterm.o \ + fevent.o \ + foptimove.o \ + fapp.o \ + fwidget.o \ + fobject.o TERMCAP := $(shell test -n "$$(ldd {/usr,}/lib64/libncursesw.so.5 2>/dev/null | grep libtinfo)" && echo "-ltinfo" || echo "-lncurses") diff --git a/src/Makefile.gcc b/src/Makefile.gcc index cdae9263..094b2a9a 100644 --- a/src/Makefile.gcc +++ b/src/Makefile.gcc @@ -7,33 +7,38 @@ VERSION = "0.1.1" MAJOR := $(shell echo ${VERSION} | cut -d. -f1) LIBDIR = /usr/local/lib64 INCLUDEDIR = /usr/local/include/final -INCLUDE_HEADERS = fapp.h \ - fbuttongroup.h \ - fbutton.h \ - fcheckbox.h \ - fswitch.h \ - fdialog.h \ - fevent.h \ - ffiledialog.h \ - final.h \ - flabel.h \ - flineedit.h \ - flistbox.h \ - fmessagebox.h \ - fobject.h \ - foptimove.h \ - fpoint.h \ - fprogressbar.h \ - fradiobutton.h \ - frect.h \ - fscrollbar.h \ - fstatusbar.h \ - fstring.h \ - fterm.h \ - ftextview.h \ - ftogglebutton.h \ - fwidget.h \ - fwindow.h +INCLUDE_HEADERS = \ + fapp.h \ + fbuttongroup.h \ + fbutton.h \ + fcheckbox.h \ + fswitch.h \ + fdialog.h \ + fevent.h \ + ffiledialog.h \ + final.h \ + flabel.h \ + flineedit.h \ + flistbox.h \ + fmenu.h \ + fmenubar.h \ + fradiomenuitem.h \ + fcheckmenuitem.h \ + fmessagebox.h \ + fobject.h \ + foptimove.h \ + fpoint.h \ + fprogressbar.h \ + fradiobutton.h \ + frect.h \ + fscrollbar.h \ + fstatusbar.h \ + fstring.h \ + fterm.h \ + ftextview.h \ + ftogglebutton.h \ + fwidget.h \ + fwindow.h # compiler parameter CXX = g++ @@ -45,32 +50,39 @@ GPM = -D F_HAVE_LIBGPM VER = -D F_VERSION=$(VERSION) RM = rm -f LIB = libfinal.so -OBJS = fstring.o \ - fpoint.o \ - frect.o \ - fscrollbar.o \ - fprogressbar.o \ - flineedit.o \ - fbutton.o \ - fbuttongroup.o \ - ftogglebutton.o \ - fradiobutton.o \ - fcheckbox.o \ - fswitch.o \ - flabel.o \ - flistbox.o \ - fdialog.o \ - fwindow.o \ - fmessagebox.o \ - ffiledialog.o \ - ftextview.o \ - fstatusbar.o \ - fterm.o \ - fevent.o \ - foptimove.o \ - fapp.o \ - fwidget.o \ - fobject.o +OBJS = \ + fstring.o \ + fpoint.o \ + frect.o \ + fscrollbar.o \ + fprogressbar.o \ + flineedit.o \ + fbutton.o \ + fbuttongroup.o \ + ftogglebutton.o \ + fradiobutton.o \ + fcheckbox.o \ + fswitch.o \ + flabel.o \ + flistbox.o \ + fmenu.o \ + fmenubar.o \ + fmenuitem.o \ + fradiomenuitem.o \ + fcheckmenuitem.o \ + fmenulist.o \ + fdialog.o \ + fwindow.o \ + fmessagebox.o \ + ffiledialog.o \ + ftextview.o \ + fstatusbar.o \ + fterm.o \ + fevent.o \ + foptimove.o \ + fapp.o \ + fwidget.o \ + fobject.o TERMCAP := $(shell test -n "$$(ldd {/usr,}/lib64/libncursesw.so.5 2>/dev/null | grep libtinfo)" && echo "-ltinfo" || echo "-lncurses") diff --git a/src/Makefile.in b/src/Makefile.in index 2e2ea0b7..120408fb 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -132,9 +132,10 @@ am_libfinal_la_OBJECTS = fstring.lo fpoint.lo frect.lo fscrollbar.lo \ fprogressbar.lo flineedit.lo fbutton.lo fbuttongroup.lo \ ftogglebutton.lo fradiobutton.lo fcheckbox.lo fswitch.lo \ flabel.lo flistbox.lo fmenu.lo fmenubar.lo fmenuitem.lo \ - fmenulist.lo fdialog.lo fwindow.lo fmessagebox.lo \ - ffiledialog.lo ftextview.lo fstatusbar.lo fterm.lo fevent.lo \ - foptimove.lo fapp.lo fwidget.lo fobject.lo + fradiomenuitem.lo fcheckmenuitem.lo fmenulist.lo fdialog.lo \ + fwindow.lo fmessagebox.lo ffiledialog.lo ftextview.lo \ + fstatusbar.lo fterm.lo fevent.lo foptimove.lo fapp.lo \ + fwidget.lo fobject.lo libfinal_la_OBJECTS = $(am_libfinal_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -389,6 +390,8 @@ libfinal_la_SOURCES = \ fmenu.cpp \ fmenubar.cpp \ fmenuitem.cpp \ + fradiomenuitem.cpp \ + fcheckmenuitem.cpp \ fmenulist.cpp \ fdialog.cpp \ fwindow.cpp \ @@ -425,6 +428,8 @@ finalcutinclude_HEADERS = \ fmenu.h \ fmenubar.h \ fmenuitem.h \ + fradiomenuitem.h \ + fcheckmenuitem.h \ fmenulist.h \ fmessagebox.h \ fobject.h \ @@ -526,6 +531,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fbutton.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fbuttongroup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcheckbox.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcheckmenuitem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fevent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ffiledialog.Plo@am__quote@ @@ -542,6 +548,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpoint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fprogressbar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fradiobutton.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fradiomenuitem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fscrollbar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fstatusbar.Plo@am__quote@ diff --git a/src/fcharmap.h b/src/fcharmap.h index 9e522f61..4a74b690 100644 --- a/src/fcharmap.h +++ b/src/fcharmap.h @@ -107,7 +107,8 @@ static uInt character[][fc::NUM_OF_ENCODINGS] = {0x1ae9, 0, 0xe9, 0}, // ◤ - NF_rev_down_pointing_triangle2 {0x1af4, 0, 0xf4, 0}, // ] - NF_rev_menu_button3 {0x1af5, 0, 0xf5, 0}, // ] - NF_shadow_box_right - {0x1afb, 0, 0xfb, 0} // ✓ - NF_check_mark + {0x1afb, 0, 0xfb, 0}, // ✓ - NF_check_mark + {0x221a, 0, 0xfb, 'x'} // √ - square root }; const int lastCharItem = int(sizeof(character) / sizeof(character[0])) - 1; diff --git a/src/fcheckmenuitem.cpp b/src/fcheckmenuitem.cpp new file mode 100644 index 00000000..37531cfe --- /dev/null +++ b/src/fcheckmenuitem.cpp @@ -0,0 +1,74 @@ +// File: fcheckmenuitem.cpp +// Provides: class FCheckMenuItem + +#include "fcheckmenuitem.h" +#include "fmenu.h" + +//---------------------------------------------------------------------- +// class FCheckMenuItem +//---------------------------------------------------------------------- + +// constructor and destructor +//---------------------------------------------------------------------- +FCheckMenuItem::FCheckMenuItem (FWidget* parent) + : FMenuItem(parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FCheckMenuItem::FCheckMenuItem (FString& txt, FWidget* parent) + : FMenuItem(txt, parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FCheckMenuItem::FCheckMenuItem (const std::string& txt, FWidget* parent) + : FMenuItem(txt, parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FCheckMenuItem::FCheckMenuItem (const char* txt, FWidget* parent) + : FMenuItem(txt, parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FCheckMenuItem::~FCheckMenuItem() // destructor +{ } + + +// private methods of FCheckMenuItem +//---------------------------------------------------------------------- +void FCheckMenuItem::init (FWidget* parent) +{ + checkable = true; + + if ( parent ) + { + if ( isMenu(parent) ) // Parent is menu + { + FMenu* menu_ptr = dynamic_cast(parent); + if ( menu_ptr ) + menu_ptr->has_checkable_items = true; + } + } +} + +//---------------------------------------------------------------------- +void FCheckMenuItem::processToggle() +{ + emitCallback("toggled"); +} + +//---------------------------------------------------------------------- +void FCheckMenuItem::processClicked() +{ + checked = not checked; + processToggle(); + emitCallback("clicked"); +} diff --git a/src/fcheckmenuitem.h b/src/fcheckmenuitem.h new file mode 100644 index 00000000..03d6f5fc --- /dev/null +++ b/src/fcheckmenuitem.h @@ -0,0 +1,66 @@ +// File: fcheckmenuitem.h +// Provides: class FCheckMenuItem +// +// Inheritance diagram +// ═══════════════════ +// +// ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▏ +// ▕ FObject ▏ ▕ FTerm ▏ +// ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏ +// ▲ ▲ +// │ │ +// └─────┬─────┘ +// │ +// ▕▔▔▔▔▔▔▔▔▔▏ +// ▕ FWidget ▏ +// ▕▁▁▁▁▁▁▁▁▁▏ +// ▲ +// │ +// ▕▔▔▔▔▔▔▔▔▔▔▔▏ +// ▕ FMenuItem ▏ +// ▕▁▁▁▁▁▁▁▁▁▁▁▏ +// ▲ +// │ +// ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏* 1▕▔▔▔▔▔▔▔▏ +// ▕ FCheckMenuItem ▏- - - - -▕ FMenu ▏ +// ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▏ + +#ifndef _FCHECKMENUITEM_H +#define _FCHECKMENUITEM_H + +#include "fmenuitem.h" + + +//---------------------------------------------------------------------- +// class FCheckMenuItem +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FCheckMenuItem : public FMenuItem +{ + private: + FCheckMenuItem (const FCheckMenuItem&); + FCheckMenuItem& operator = (const FCheckMenuItem&); + void init (FWidget*); + void processToggle(); + void processClicked(); + + public: + explicit FCheckMenuItem (FWidget* = 0); + FCheckMenuItem (FString&, FWidget* = 0); + FCheckMenuItem (const std::string&, FWidget* = 0); + FCheckMenuItem (const char*, FWidget* = 0); + virtual ~FCheckMenuItem(); + const char* getClassName() const; +}; +#pragma pack(pop) + + +// FCheckMenuItem inline functions +//---------------------------------------------------------------------- +inline const char* FCheckMenuItem::getClassName() const +{ return "FCheckMenuItem"; } + +#endif // _FCHECKMENUITEM_H diff --git a/src/fenum.h b/src/fenum.h index f7ae9f3c..e647a1f2 100644 --- a/src/fenum.h +++ b/src/fenum.h @@ -165,7 +165,8 @@ class fc NF_rev_down_pointing_triangle2 = 0x1ae9, // ◤ NF_rev_menu_button3 = 0x1af4, // ] NF_shadow_box_right = 0x1af5, // ] - NF_check_mark = 0x1afb // ✓ + NF_check_mark = 0x1afb, // ✓ + SquareRoot = 0x221a // √ }; // keyboard - single keys diff --git a/src/final.h b/src/final.h index 3de2568f..fea9802b 100644 --- a/src/final.h +++ b/src/final.h @@ -22,6 +22,8 @@ #include "fmenu.h" #include "fmenubar.h" #include "fmenuitem.h" +#include "fcheckmenuitem.h" +#include "fradiomenuitem.h" #include "fstatusbar.h" #include "fscrollbar.h" #include "fprogressbar.h" diff --git a/src/fmenu.cpp b/src/fmenu.cpp index 0d1cb60f..dadbfd4d 100644 --- a/src/fmenu.cpp +++ b/src/fmenu.cpp @@ -17,6 +17,7 @@ FMenu::FMenu(FWidget* parent) , super_menu(0) , maxItemWidth(0) , mouse_down(false) + , has_checkable_items(false) { init(parent); } @@ -28,6 +29,7 @@ FMenu::FMenu (FString& txt, FWidget* parent) , super_menu(0) , maxItemWidth(0) , mouse_down(false) + , has_checkable_items(false) { item = new FMenuItem(txt, parent); init(parent); @@ -40,6 +42,7 @@ FMenu::FMenu (const std::string& txt, FWidget* parent) , super_menu(0) , maxItemWidth(0) , mouse_down(false) + , has_checkable_items(false) { item = new FMenuItem(txt, parent); init(parent); @@ -52,6 +55,7 @@ FMenu::FMenu (const char* txt, FWidget* parent) , super_menu(0) , maxItemWidth(0) , mouse_down(false) + , has_checkable_items(false) { item = new FMenuItem(txt, parent); init(parent); @@ -141,6 +145,9 @@ void FMenu::menu_dimension() item_width += accel_len + 2; } + if ( has_checkable_items ) + item_width++; + if ( item_width > maxItemWidth ) maxItemWidth = item_width; @@ -178,6 +185,13 @@ bool FMenu::isMenu (FWidget* w) const , const_cast("FMenu") ) == 0 ); } +//---------------------------------------------------------------------- +bool FMenu::isRadioMenuItem (FWidget* w) const +{ + return bool ( strcmp ( w->getClassName() + , const_cast("FRadioMenuItem") ) == 0 ); +} + //---------------------------------------------------------------------- void FMenu::hideSubMenus() { @@ -483,11 +497,14 @@ void FMenu::drawMenuShadow() void FMenu::drawItems() { std::vector::const_iterator iter, end; + int c = 0; int y = 0; - iter = itemlist.begin(); end = itemlist.end(); + if ( has_checkable_items ) + c = 1; + while ( iter != end ) { wchar_t* src; @@ -498,6 +515,9 @@ void FMenu::drawItems() int hotkeypos, to_char; int accel_key = (*iter)->accel_key; bool is_enabled = (*iter)->isEnabled(); + bool is_checked = (*iter)->isChecked(); + bool is_checkable = (*iter)->checkable; + bool is_radio_btn = (*iter)->radio_button; bool is_selected = (*iter)->isSelected(); bool is_noUnderline = (((*iter)->getFlags() & NO_UNDERLINE) != 0); bool is_separator = (*iter)->isSeparator(); @@ -534,6 +554,34 @@ void FMenu::drawItems() } gotoxy (xpos+xmin, ypos+ymin+y); setColor (foregroundColor, backgroundColor); + if ( has_checkable_items ) + { + if ( is_checkable ) + { + if ( is_checked ) + { + if ( is_radio_btn ) + { + print (fc::Bullet); + } + else + { + if ( isNewFont() ) + print (fc::NF_check_mark); + else + print (fc::SquareRoot); + } + } + else + { + setColor (wc.menu_inactive_fg, backgroundColor); + print ('-'); + setColor (foregroundColor, backgroundColor); + } + } + else + print (' '); + } print (' '); txt = (*iter)->getText(); @@ -587,18 +635,18 @@ void FMenu::drawItems() { FString accel_name (getKeyName(accel_key)); int accel_len = int(accel_name.getLength()); - int len = maxItemWidth - (to_char + accel_len + 2); + int len = maxItemWidth - (to_char + accel_len + c + 2); if ( len > 0 ) { - FString line(len, wchar_t(' ')); - print (line + accel_name); - to_char = maxItemWidth - 2; + FString spaces (len, wchar_t(' ')); + print (spaces + accel_name); + to_char = maxItemWidth - (c + 2); } } if ( is_selected ) { - for (uInt i=uInt(to_char); i < maxItemWidth-1; i++) + for (uInt i=uInt(to_char+c); i < maxItemWidth-1; i++) print (' '); } @@ -950,6 +998,7 @@ void FMenu::onMouseMove (FMouseEvent* ev) ev = new FMouseEvent (MouseMove_Event, p, g, b); setClickedWidget(menubar); FMenuBar* mbar = reinterpret_cast(menubar); + mbar->mouse_down = true; mbar->onMouseMove(ev); delete ev; } @@ -1042,6 +1091,34 @@ void FMenu::cb_menuitem_activated (FWidget* widget, void*) } } +//---------------------------------------------------------------------- +void FMenu::cb_menuitem_toggled (FWidget* widget, void*) +{ + FMenuItem* menuitem = static_cast(widget); + std::vector::const_iterator iter, end; + + if ( ! has_checkable_items ) + return; + if ( ! menuitem->isChecked() ) + return; + if ( itemlist.empty() ) + return; + + iter = itemlist.begin(); + end = itemlist.end(); + + while ( iter != end ) + { + if ( (*iter) != menuitem + && (*iter)->isChecked() + && isRadioMenuItem(*iter) ) + { + (*iter)->unsetChecked(); + } + ++iter; + } +} + //---------------------------------------------------------------------- bool FMenu::setTransparentShadow (bool on) { @@ -1065,13 +1142,3 @@ bool FMenu::setTransparentShadow (bool on) return on; } -//---------------------------------------------------------------------- -void FMenu::cb_menuitem_deactivated (FWidget* widget, void*) -{ - FMenuItem* menuitem = static_cast(widget); - - if ( menuitem->hasMenu() ) - { - //beep(); - } -} diff --git a/src/fmenu.h b/src/fmenu.h index 0189601a..1c4c8881 100644 --- a/src/fmenu.h +++ b/src/fmenu.h @@ -8,15 +8,15 @@ // ▕ FObject ▏ ▕ FTerm ▏ // ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏ // ▲ ▲ -// │ │ -// └─────┬─────┘ -// │ -// ▕▔▔▔▔▔▔▔▔▔▏ -// ▕ FWidget ▏ -// ▕▁▁▁▁▁▁▁▁▁▏ -// ▲ -// │ -// ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▏ +// │ │ *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ +// └─────┬─────┘ ┌ - -▕ FRadioMenuItem ▏ +// │ : ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ +// ▕▔▔▔▔▔▔▔▔▔▏ : +// ▕ FWidget ▏ : *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ +// ▕▁▁▁▁▁▁▁▁▁▏ ├ - -▕ FCheckMenuItem ▏ +// ▲ : ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ +// │ 1 : +// ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▔▔▏- ┘ ▕▔▔▔▔▔▔▔▔▔▔▔▏ // ▕ FWindow ▏ ▕ FMenuList ▏- - - -▕ FMenuItem ▏ // ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▏1 *▕▁▁▁▁▁▁▁▁▁▁▁▏ // ▲ ▲ 1: @@ -50,6 +50,7 @@ class FMenu : public FWindow, public FMenuList FWidget* super_menu; uInt maxItemWidth; bool mouse_down; + bool has_checkable_items; private: FMenu (const FMenu&); @@ -58,6 +59,7 @@ class FMenu : public FWindow, public FMenuList void menu_dimension(); bool isMenuBar (FWidget*) const; bool isMenu (FWidget*) const; + bool isRadioMenuItem (FWidget*) const; FWidget* getSuperMenu() const; void setSuperMenu (FWidget*); void hideSubMenus(); @@ -116,12 +118,14 @@ class FMenu : public FWindow, public FMenuList void setText (const std::string&); void setText (const char*); void cb_menuitem_activated (FWidget*, void*); - void cb_menuitem_deactivated (FWidget*, void*); + void cb_menuitem_toggled (FWidget*, void*); private: friend class FApplication; + friend class FCheckMenuItem; friend class FMenuBar; friend class FMenuItem; + friend class FRadioMenuItem; }; #pragma pack(pop) diff --git a/src/fmenubar.cpp b/src/fmenubar.cpp index e567376d..f4deb357 100644 --- a/src/fmenubar.cpp +++ b/src/fmenubar.cpp @@ -442,6 +442,21 @@ void FMenuBar::adjustSize() FWidget::adjustSize(); } +//---------------------------------------------------------------------- +void FMenuBar::leaveMenuBar() +{ + resetMenu(); + redraw(); + activatePrevWindow(); + getActiveWindow()->getFocusWidget()->setFocus(); + getActiveWindow()->redraw(); + if ( statusBar() ) + statusBar()->drawMessage(); + updateTerminal(); + flush_out(); + drop_down = false; +} + // public methods of FMenuBar //---------------------------------------------------------------------- void FMenuBar::onKeyPress (FKeyEvent* ev) @@ -494,16 +509,7 @@ void FMenuBar::onKeyPress (FKeyEvent* ev) case fc::Fkey_escape: case fc::Fkey_escape_mintty: - resetMenu(); - redraw(); - activatePrevWindow(); - getActiveWindow()->getFocusWidget()->setFocus(); - getActiveWindow()->redraw(); - if ( statusBar() ) - statusBar()->drawMessage(); - updateTerminal(); - flush_out(); - drop_down = false; + leaveMenuBar(); ev->accept(); break; @@ -519,11 +525,7 @@ void FMenuBar::onMouseDown (FMouseEvent* ev) { mouse_down = false; if ( ! itemlist.empty() ) - { - unselectItem(); - redraw(); - drop_down = false; - } + leaveMenuBar(); return; } @@ -675,6 +677,8 @@ void FMenuBar::onMouseUp (FMouseEvent* ev) } ++iter; } + if ( ! hasSelectedItem() ) + leaveMenuBar(); } } } @@ -827,11 +831,6 @@ void FMenuBar::setGeometry (int xx, int yy, int ww, int hh, bool adjust) resizeArea (vmenubar); } -//---------------------------------------------------------------------- -void FMenuBar::cb_item_activated (FWidget*, void*) -{ -} - //---------------------------------------------------------------------- void FMenuBar::cb_item_deactivated (FWidget* widget, void*) { diff --git a/src/fmenubar.h b/src/fmenubar.h index 77b174ab..42284cd0 100644 --- a/src/fmenubar.h +++ b/src/fmenubar.h @@ -61,6 +61,7 @@ class FMenuBar : public FWindow, public FMenuList void draw(); void drawItems(); void adjustSize(); + void leaveMenuBar(); public: explicit FMenuBar (FWidget* = 0); // constructor @@ -77,7 +78,6 @@ class FMenuBar : public FWindow, public FMenuList // make every setGeometry from FWidget available using FWidget::setGeometry; void setGeometry (int, int, int, int, bool = true); - void cb_item_activated (FWidget*, void*); void cb_item_deactivated (FWidget*, void*); private: diff --git a/src/fmenuitem.cpp b/src/fmenuitem.cpp index 9f74be66..a06b43a6 100644 --- a/src/fmenuitem.cpp +++ b/src/fmenuitem.cpp @@ -19,12 +19,14 @@ FMenuItem::FMenuItem (FWidget* parent) , text() , selected(false) , separator(false) + , checkable(false) , checked(false) , text_length(0) , hotkey(0) , accel_key(0) , menu(0) , super_menu(0) + , radio_button(false) { init (parent); } @@ -35,12 +37,14 @@ FMenuItem::FMenuItem (FString& txt, FWidget* parent) , text(txt) , selected(false) , separator(false) + , checkable(false) , checked(false) , text_length(0) , hotkey(0) , accel_key(0) , menu(0) , super_menu(0) + , radio_button(false) { init (parent); } @@ -51,12 +55,14 @@ FMenuItem::FMenuItem (const std::string& txt, FWidget* parent) , text(txt) , selected(false) , separator(false) + , checkable(false) , checked(false) , text_length(0) , hotkey(0) , accel_key(0) , menu(0) , super_menu(0) + , radio_button(false) { init (parent); } @@ -67,27 +73,32 @@ FMenuItem::FMenuItem (const char* txt, FWidget* parent) , text(txt) , selected(false) , separator(false) + , checkable(false) , checked(false) , text_length(0) , hotkey(0) , accel_key(0) , menu(0) , super_menu(0) + , radio_button(false) { init (parent); } + //---------------------------------------------------------------------- FMenuItem::FMenuItem (int k, FString& txt, FWidget* parent) : FWidget(parent) , text(txt) , selected(false) , separator(false) + , checkable(false) , checked(false) , text_length(0) , hotkey(0) , accel_key(k) , menu(0) , super_menu(0) + , radio_button(false) { init (parent); } @@ -98,12 +109,14 @@ FMenuItem::FMenuItem (int k, const std::string& txt, FWidget* parent) , text(txt) , selected(false) , separator(false) + , checkable(false) , checked(false) , text_length(0) , hotkey(0) , accel_key(k) , menu(0) , super_menu(0) + , radio_button(false) { init (parent); } @@ -114,15 +127,18 @@ FMenuItem::FMenuItem (int k, const char* txt, FWidget* parent) , text(txt) , selected(false) , separator(false) + , checkable(false) , checked(false) , text_length(0) , hotkey(0) , accel_key(k) , menu(0) , super_menu(0) + , radio_button(false) { init (parent); } + //---------------------------------------------------------------------- FMenuItem::~FMenuItem() // destructor { @@ -164,15 +180,10 @@ void FMenuItem::init (FWidget* parent) if ( hotkey ) menubar_ptr->addAccelerator (fc::Fmkey_meta + tolower(hotkey), this); - this->addCallback - ( - "activate", - _METHOD_CALLBACK (getSuperMenu(), &FMenuBar::cb_item_activated) - ); this->addCallback ( "deactivate", - _METHOD_CALLBACK (getSuperMenu(), &FMenuBar::cb_item_deactivated) + _METHOD_CALLBACK (parent, &FMenuBar::cb_item_deactivated) ); } else if ( isMenu(parent) ) // Parent is menu @@ -184,12 +195,7 @@ void FMenuItem::init (FWidget* parent) this->addCallback ( "activate", - _METHOD_CALLBACK (getSuperMenu(), &FMenu::cb_menuitem_activated) - ); - this->addCallback - ( - "deactivate", - _METHOD_CALLBACK (getSuperMenu(), &FMenu::cb_menuitem_deactivated) + _METHOD_CALLBACK (parent, &FMenu::cb_menuitem_activated) ); } } @@ -225,20 +231,6 @@ uChar FMenuItem::hotKey() return 0; } -//---------------------------------------------------------------------- -bool FMenuItem::isMenuBar (FWidget* w) const -{ - return bool ( strcmp ( w->getClassName() - , const_cast("FMenuBar") ) == 0 ); -} - -//---------------------------------------------------------------------- -bool FMenuItem::isMenu (FWidget* w) const -{ - return bool ( strcmp ( w->getClassName() - , const_cast("FMenu") ) == 0 ); -} - //---------------------------------------------------------------------- void FMenuItem::processActivate() { @@ -257,6 +249,23 @@ void FMenuItem::processClicked() emitCallback("clicked"); } + +// protected methods of FMenuItem +//---------------------------------------------------------------------- +bool FMenuItem::isMenuBar (FWidget* w) const +{ + return bool ( strcmp ( w->getClassName() + , const_cast("FMenuBar") ) == 0 ); +} + +//---------------------------------------------------------------------- +bool FMenuItem::isMenu (FWidget* w) const +{ + return bool ( strcmp ( w->getClassName() + , const_cast("FMenu") ) == 0 ); +} + + // public methods of FMenuItem //---------------------------------------------------------------------- void FMenuItem::addAccelerator (int key, FWidget* obj) diff --git a/src/fmenuitem.h b/src/fmenuitem.h index b4873da1..c53dbcdc 100644 --- a/src/fmenuitem.h +++ b/src/fmenuitem.h @@ -16,11 +16,11 @@ // ▕▁▁▁▁▁▁▁▁▁▏ // ▲ // │ -// ▕▔▔▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▏ +// ▕▔▔▔▔▔▔▔▔▔▔▔▏* 1▕▔▔▔▔▔▔▔▏ // ▕ FMenuItem ▏-┬- - - -▕ FMenu ▏ // ▕▁▁▁▁▁▁▁▁▁▁▁▏ : ▕▁▁▁▁▁▁▁▏ // : -// : *▕▔▔▔▔▔▔▔▔▔▔▔▏ +// : 1▕▔▔▔▔▔▔▔▔▔▔▔▏ // └- - - -▕ FMenuList ▏ // ▕▁▁▁▁▁▁▁▁▁▁▁▏ @@ -42,29 +42,33 @@ class FMenuList; class FMenuItem : public FWidget { - private: + protected: FString text; bool selected; bool separator; + bool checkable; bool checked; uInt text_length; int hotkey; int accel_key; FMenu* menu; FWidget* super_menu; + bool radio_button; private: FMenuItem (const FMenuItem&); FMenuItem& operator = (const FMenuItem&); void init (FWidget*); uChar hotKey(); + void processActivate(); + void processDeactivate(); + virtual void processClicked(); + + protected: bool isMenuBar (FWidget*) const; bool isMenu (FWidget*) const; FWidget* getSuperMenu() const; void setSuperMenu (FWidget*); - void processActivate(); - void processDeactivate(); - void processClicked(); public: explicit FMenuItem (FWidget* = 0); @@ -75,6 +79,7 @@ class FMenuItem : public FWidget FMenuItem (int, const std::string&, FWidget* = 0); FMenuItem (int, const char*, FWidget* = 0); virtual ~FMenuItem(); + const char* getClassName() const; // make every addAccelerator from FWidget available using FWidget::addAccelerator; @@ -125,6 +130,10 @@ class FMenuItem : public FWidget // FMenuItem inline functions +//---------------------------------------------------------------------- +inline const char* FMenuItem::getClassName() const +{ return "FMenuItem"; } + //---------------------------------------------------------------------- inline FWidget* FMenuItem::getSuperMenu() const { return super_menu; } diff --git a/src/fmenulist.h b/src/fmenulist.h index e62b4419..d951d735 100644 --- a/src/fmenulist.h +++ b/src/fmenulist.h @@ -7,7 +7,14 @@ // ▕▔▔▔▔▔▔▔▔▔▔▔▏1 *▕▔▔▔▔▔▔▔▔▔▔▔▏ // ▕ FMenuList ▏- - - -▕ FMenuItem ▏ // ▕▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▁▁▏ - +// :1 +// : *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ +// ├- - - - - - -▕ FRadioMenuItem ▏ +// : ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ +// : +// : *▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏ +// └- - - - - - -▕ FCheckMenuItem ▏ +// ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ #ifndef _FMENULIST_H #define _FMENULIST_H @@ -15,18 +22,6 @@ #include "fmenuitem.h" #include "fwidget.h" -/* - ┌─────────┐ ┌──────────┐ - │ FWindow │◄───┐ ┌───┤ FMenuBar │ - └─────────┘ │ │ └──────────┘ - ├──┤ - ┌───────────┐ │ │ ┌───────┐ - │ FMenuList │◄───┘ └───┤ FMenu │ - └─────┬─────┘ └───────┘ - : ┌───────────┐ - └-----------------┤ FMenuItem │ - └───────────┘ -*/ //---------------------------------------------------------------------- // class FMenuList diff --git a/src/fradiomenuitem.cpp b/src/fradiomenuitem.cpp new file mode 100644 index 00000000..d99a8849 --- /dev/null +++ b/src/fradiomenuitem.cpp @@ -0,0 +1,85 @@ +// File: fradiomenuitem.cpp +// Provides: class FRadioMenuItem + +#include "fradiomenuitem.h" +#include "fmenu.h" + +//---------------------------------------------------------------------- +// class FRadioMenuItem +//---------------------------------------------------------------------- + +// constructor and destructor +//---------------------------------------------------------------------- +FRadioMenuItem::FRadioMenuItem (FWidget* parent) + : FMenuItem(parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FRadioMenuItem::FRadioMenuItem (FString& txt, FWidget* parent) + : FMenuItem(txt, parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FRadioMenuItem::FRadioMenuItem (const std::string& txt, FWidget* parent) + : FMenuItem(txt, parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FRadioMenuItem::FRadioMenuItem (const char* txt, FWidget* parent) + : FMenuItem(txt, parent) +{ + init (parent); +} + +//---------------------------------------------------------------------- +FRadioMenuItem::~FRadioMenuItem() // destructor +{ } + + +// private methods of FRadioMenuItem +//---------------------------------------------------------------------- +void FRadioMenuItem::init (FWidget* parent) +{ + checkable = true; + radio_button = true; + + if ( parent ) + { + if ( isMenu(parent) ) // Parent is menu + { + FMenu* menu_ptr = dynamic_cast(parent); + if ( menu_ptr ) + menu_ptr->has_checkable_items = true; + + this->addCallback + ( + "toggled", + _METHOD_CALLBACK (parent, &FMenu::cb_menuitem_toggled) + ); + } + } +} + +//---------------------------------------------------------------------- +void FRadioMenuItem::processToggle() +{ + emitCallback("toggled"); +} + +//---------------------------------------------------------------------- +void FRadioMenuItem::processClicked() +{ + if ( ! checked ) + { + checked = true; + processToggle(); + } + + emitCallback("clicked"); +} diff --git a/src/fradiomenuitem.h b/src/fradiomenuitem.h new file mode 100644 index 00000000..9ec03f42 --- /dev/null +++ b/src/fradiomenuitem.h @@ -0,0 +1,66 @@ +// File: fradiomenuitem.h +// Provides: class FRadioMenuItem +// +// Inheritance diagram +// ═══════════════════ +// +// ▕▔▔▔▔▔▔▔▔▔▏ ▕▔▔▔▔▔▔▔▔▔▏ +// ▕ FObject ▏ ▕ FTerm ▏ +// ▕▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▁▁▏ +// ▲ ▲ +// │ │ +// └─────┬─────┘ +// │ +// ▕▔▔▔▔▔▔▔▔▔▏ +// ▕ FWidget ▏ +// ▕▁▁▁▁▁▁▁▁▁▏ +// ▲ +// │ +// ▕▔▔▔▔▔▔▔▔▔▔▔▏ +// ▕ FMenuItem ▏ +// ▕▁▁▁▁▁▁▁▁▁▁▁▏ +// ▲ +// │ +// ▕▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▏* 1▕▔▔▔▔▔▔▔▏ +// ▕ FRadioMenuItem ▏- - - - -▕ FMenu ▏ +// ▕▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▏ ▕▁▁▁▁▁▁▁▏ + +#ifndef _FRADIOMENUITEM_H +#define _FRADIOMENUITEM_H + +#include "fmenuitem.h" + + +//---------------------------------------------------------------------- +// class FRadioMenuItem +//---------------------------------------------------------------------- + +#pragma pack(push) +#pragma pack(1) + +class FRadioMenuItem : public FMenuItem +{ + private: + FRadioMenuItem (const FRadioMenuItem&); + FRadioMenuItem& operator = (const FRadioMenuItem&); + void init (FWidget*); + void processToggle(); + void processClicked(); + + public: + explicit FRadioMenuItem (FWidget* = 0); + FRadioMenuItem (FString&, FWidget* = 0); + FRadioMenuItem (const std::string&, FWidget* = 0); + FRadioMenuItem (const char*, FWidget* = 0); + virtual ~FRadioMenuItem(); + const char* getClassName() const; +}; +#pragma pack(pop) + + +// FRadioMenuItem inline functions +//---------------------------------------------------------------------- +inline const char* FRadioMenuItem::getClassName() const +{ return "FRadioMenuItem"; } + +#endif // _FRADIOMENUITEM_H diff --git a/src/fstring.cpp b/src/fstring.cpp index b081d558..51e2d3b5 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -24,7 +24,7 @@ FString::FString (int len) , bufsize(0) , c_string(0) { - if ( len >= 0 ) + if ( len > 0 ) initLength(uInt(len)); else initLength(0); @@ -47,7 +47,7 @@ FString::FString (int len, wchar_t c) , bufsize(0) , c_string(0) { - if ( len >= 0 ) + if ( len > 0 ) _replace ( FString(uInt(len), c).string ); else initLength(0); @@ -83,7 +83,7 @@ FString::FString (int len, char c) bufsize = 0; c_string = 0; - if ( len >= 0 ) + if ( len > 0 ) _replace ( FString(uInt(len), c).string ); else initLength(0);