First working version of an application menu
This commit is contained in:
parent
ff8394d9f3
commit
18a7d991ff
|
@ -1,3 +1,8 @@
|
|||
2015-11-01 Markus Gans <guru.mail@muenster.de>
|
||||
* First working version of an application menu,
|
||||
it uses the new classes FMenuBar, FMenu and FMenuItem
|
||||
(alpha state)
|
||||
|
||||
2015-10-29 Markus Gans <guru.mail@muenster.de>
|
||||
* Support for the menu key
|
||||
|
||||
|
|
6
doc/TODO
6
doc/TODO
|
@ -4,6 +4,7 @@ Bugs
|
|||
|
||||
Improvements
|
||||
~~~~~~~~~~~~
|
||||
- Stabilize the application menu classes (FMenuBar, FMenu, FMenuItem)
|
||||
- If t_exit_underline_mode == "\E[24m"
|
||||
-> implement t_exit_bold_mode with "\E[21m"
|
||||
-> implement t_exit_reverse_mode with "\E[27m"
|
||||
|
@ -15,11 +16,6 @@ Improvements
|
|||
|
||||
Missing Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
- application menu
|
||||
- FMenuBar()
|
||||
- FMenu()
|
||||
- FMenuItem()
|
||||
|
||||
- list/tree view with Columns
|
||||
- FListView()
|
||||
---------------------------------------
|
||||
|
|
|
@ -347,8 +347,11 @@ void FApplication::processKeyboardEvent()
|
|||
}
|
||||
else
|
||||
{
|
||||
// send key down event
|
||||
FKeyEvent k_down_ev (KeyDown_Event, key);
|
||||
sendEvent (widget, &k_down_ev);
|
||||
|
||||
// send key press event
|
||||
FKeyEvent k_press_ev (KeyPress_Event, key);
|
||||
sendEvent (widget, &k_press_ev);
|
||||
|
||||
|
@ -384,6 +387,7 @@ void FApplication::processKeyboardEvent()
|
|||
}
|
||||
fifo_offset = int(strlen(fifo_buf));
|
||||
}
|
||||
// send key up event
|
||||
FKeyEvent k_up_ev (KeyUp_Event, key);
|
||||
sendEvent (widget, &k_up_ev);
|
||||
key = 0;
|
||||
|
|
128
src/fmenu.cpp
128
src/fmenu.cpp
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "fapp.h"
|
||||
#include "fmenu.h"
|
||||
#include "fmessagebox.h" // <----- remove later
|
||||
#include "fstatusbar.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -113,8 +112,17 @@ void FMenu::init(FWidget* parent)
|
|||
item->setMenu(this);
|
||||
|
||||
if ( parent )
|
||||
{
|
||||
if ( isMenuBar(parent) )
|
||||
{
|
||||
FMenuBar* mb = dynamic_cast<FMenuBar*>(parent);
|
||||
if ( mb )
|
||||
mb->menu_dimension();
|
||||
}
|
||||
setSuperMenu(parent);
|
||||
}
|
||||
menu_dimension();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FMenu::menu_dimension()
|
||||
|
@ -123,7 +131,7 @@ void FMenu::menu_dimension()
|
|||
std::vector<FMenuItem*>::const_iterator iter, end;
|
||||
iter = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
maxItemWidth = 0;
|
||||
maxItemWidth = 10;
|
||||
|
||||
// find the max item width
|
||||
while ( iter != end )
|
||||
|
@ -451,7 +459,6 @@ void FMenu::drawItems()
|
|||
uInt txt_length;
|
||||
int hotkeypos, to_char;
|
||||
bool is_enabled = (*iter)->isEnabled();
|
||||
bool has_focus = (*iter)->hasFocus();
|
||||
bool is_selected = (*iter)->isSelected();
|
||||
bool is_noUnderline = (((*iter)->getFlags() & NO_UNDERLINE) != 0);
|
||||
bool is_separator = (*iter)->isSeparator();
|
||||
|
@ -475,12 +482,16 @@ void FMenu::drawItems()
|
|||
{
|
||||
foregroundColor = wc.menu_active_fg;
|
||||
backgroundColor = wc.menu_active_bg;
|
||||
if ( isMonochron() )
|
||||
setReverse(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foregroundColor = wc.menu_inactive_fg;
|
||||
backgroundColor = wc.menu_inactive_bg;
|
||||
if ( isMonochron() )
|
||||
setReverse(true);
|
||||
}
|
||||
gotoxy (xpos+xmin, ypos+ymin+y);
|
||||
setColor (foregroundColor, backgroundColor);
|
||||
|
@ -494,8 +505,17 @@ void FMenu::drawItems()
|
|||
to_char = int(txt_length);
|
||||
hotkeypos = getHotkeyPos (src, dest, txt_length);
|
||||
|
||||
if ( hotkeypos != -1 )
|
||||
if ( hotkeypos == -1 )
|
||||
{
|
||||
if ( is_selected )
|
||||
setCursorPos ( xpos+xmin+1
|
||||
, ypos+ymin+y ); // first character
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( is_selected )
|
||||
setCursorPos ( xpos+xmin+1+hotkeypos
|
||||
, ypos+ymin+y ); // hotkey
|
||||
txt_length--;
|
||||
to_char--;
|
||||
}
|
||||
|
@ -534,7 +554,7 @@ void FMenu::drawItems()
|
|||
setReverse(true);
|
||||
delete[] item_text;
|
||||
}
|
||||
if ( has_focus && statusBar() )
|
||||
/*if ( is_selected && statusBar() )
|
||||
{
|
||||
FString msg = (*iter)->getStatusbarMessage();
|
||||
FString curMsg = statusBar()->getMessage();
|
||||
|
@ -543,10 +563,12 @@ void FMenu::drawItems()
|
|||
statusBar()->setMessage(msg);
|
||||
statusBar()->drawMessage();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
++iter;
|
||||
y++;
|
||||
}
|
||||
if ( hasFocus() )
|
||||
setCursor();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -554,10 +576,14 @@ inline void FMenu::drawSeparator(int y)
|
|||
{
|
||||
gotoxy (xpos+xmin-1, ypos+ymin+y);
|
||||
setColor (wc.menu_active_fg, wc.menu_active_bg);
|
||||
if ( isMonochron() )
|
||||
setReverse(true);
|
||||
print(fc::BoxDrawingsVerticalAndRight);
|
||||
FString line(width-2, wchar_t(fc::BoxDrawingsHorizontal));
|
||||
print (line);
|
||||
print(fc::BoxDrawingsVerticalAndLeft);
|
||||
if ( isMonochron() )
|
||||
setReverse(false);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -571,6 +597,40 @@ void FMenu::processActivate()
|
|||
//----------------------------------------------------------------------
|
||||
void FMenu::onKeyPress (FKeyEvent* ev)
|
||||
{
|
||||
// looking for a hotkey
|
||||
std::vector<FMenuItem*>::const_iterator iter, end;
|
||||
iter = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
|
||||
while ( iter != end )
|
||||
{
|
||||
if ( (*iter)->hasHotkey() )
|
||||
{
|
||||
bool found = false;
|
||||
int hotkey = (*iter)->getHotkey();
|
||||
int key = ev->key();
|
||||
|
||||
if ( isalpha(hotkey) || isdigit(hotkey) )
|
||||
{
|
||||
if ( tolower(hotkey) == key || toupper(hotkey) == key )
|
||||
found = true;
|
||||
}
|
||||
else if ( hotkey == key )
|
||||
found = true;
|
||||
|
||||
if ( found )
|
||||
{
|
||||
unselectItemInList();
|
||||
hide();
|
||||
hideSuperMenus();
|
||||
ev->accept();
|
||||
(*iter)->processClicked();
|
||||
return;
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
switch ( ev->key() )
|
||||
{
|
||||
case fc::Fkey_return:
|
||||
|
@ -597,7 +657,7 @@ void FMenu::onKeyPress (FKeyEvent* ev)
|
|||
break;
|
||||
|
||||
case fc::Fkey_left:
|
||||
if ( selectedListItem->hasMenu() )
|
||||
if ( hasSelectedListItem() && selectedListItem->hasMenu() )
|
||||
{
|
||||
FMenu* sub_menu = selectedListItem->getMenu();
|
||||
if ( sub_menu->isVisible() )
|
||||
|
@ -611,7 +671,7 @@ void FMenu::onKeyPress (FKeyEvent* ev)
|
|||
break;
|
||||
|
||||
case fc::Fkey_right:
|
||||
if ( selectedListItem->hasMenu() )
|
||||
if ( hasSelectedListItem() && selectedListItem->hasMenu() )
|
||||
{
|
||||
FMenu* sub_menu = selectedListItem->getMenu();
|
||||
if ( ! sub_menu->isVisible() )
|
||||
|
@ -790,16 +850,14 @@ void FMenu::onMouseMove (FMouseEvent* ev)
|
|||
y = (*iter)->getY();
|
||||
mouse_x = mouse_pos.getX();
|
||||
mouse_y = mouse_pos.getY();
|
||||
/*
|
||||
FMessageBox::info (this, "Info", FString().sprintf("local(%d,%d) global(%d,%d)\n"
|
||||
"iter x1=%d, x2=%d, y=%d"
|
||||
, ev->getX(),ev->getY(),ev->getGlobalX(), ev->getGlobalY()
|
||||
, x1, x2, y) );*/
|
||||
|
||||
if ( mouse_x >= x1
|
||||
&& mouse_x <= x2
|
||||
&& mouse_y == y )
|
||||
{
|
||||
if ( (*iter)->isEnabled() && ! (*iter)->isSelected() )
|
||||
if ( (*iter)->isEnabled()
|
||||
&& ! (*iter)->isSelected()
|
||||
&& ! (*iter)->isSeparator() )
|
||||
{
|
||||
FWidget* focused_widget = getFocusWidget();
|
||||
FFocusEvent out (FocusOut_Event);
|
||||
|
@ -829,6 +887,20 @@ FMessageBox::info (this, "Info", FString().sprintf("local(%d,%d) global(%d,%d)\n
|
|||
++iter;
|
||||
}
|
||||
|
||||
// Mouse is over border or separator
|
||||
if ( ! selectedListItem && statusBar()
|
||||
&& getGeometryGlobal().contains(ev->getGlobalPos()) )
|
||||
{
|
||||
FString msg = getStatusbarMessage();
|
||||
FString curMsg = statusBar()->getMessage();
|
||||
if ( curMsg != msg )
|
||||
{
|
||||
statusBar()->setMessage(msg);
|
||||
statusBar()->drawMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse event handover to the menu bar
|
||||
FWidget* menubar = getSuperMenu();
|
||||
if ( menubar
|
||||
&& isMenuBar(menubar)
|
||||
|
@ -897,17 +969,37 @@ void FMenu::setGeometry (int xx, int yy, int ww, int hh, bool adjust)
|
|||
resizeArea (vwin);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FMenu::setStatusbarMessage(FString msg)
|
||||
{
|
||||
FWidget::setStatusbarMessage(msg);
|
||||
if ( item )
|
||||
item->setStatusbarMessage(msg);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FMenu::selectFirstItemInList()
|
||||
{
|
||||
std::vector<FMenuItem*>::const_iterator iter, end;
|
||||
iter = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
|
||||
if ( itemlist.empty() )
|
||||
return;
|
||||
|
||||
if ( ! hasSelectedListItem() )
|
||||
if ( hasSelectedListItem() )
|
||||
unselectItemInList();
|
||||
|
||||
while ( iter != end )
|
||||
{
|
||||
// select the first item
|
||||
itemlist[0]->setSelected();
|
||||
selectedListItem = itemlist[0];
|
||||
if ( (*iter)->isEnabled() && ! (*iter)->isSeparator() )
|
||||
{
|
||||
// select first enabled item
|
||||
(*iter)->setSelected();
|
||||
selectedListItem = *iter;
|
||||
break;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ class FMenu : public FWindow, public FMenuList
|
|||
// make every setGeometry from FWidget available
|
||||
using FWidget::setGeometry;
|
||||
void setGeometry (int, int, int, int, bool = true);
|
||||
void setStatusbarMessage (FString);
|
||||
FMenuItem* getItem() const;
|
||||
FString getText() const;
|
||||
bool setEnable(bool);
|
||||
|
|
241
src/fmenubar.cpp
241
src/fmenubar.cpp
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "fapp.h"
|
||||
#include "fmenubar.h"
|
||||
#include "fstatusbar.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// class FMenuBar
|
||||
|
@ -87,6 +88,109 @@ bool FMenuBar::isMenu (FMenuItem* mi) const
|
|||
return mi->hasMenu();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool FMenuBar::selectNextItem()
|
||||
{
|
||||
std::vector<FMenuItem*>::const_iterator iter, end;
|
||||
iter = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
|
||||
while ( iter != end )
|
||||
{
|
||||
if ( (*iter)->isSelected() )
|
||||
{
|
||||
FMenuItem* next;
|
||||
std::vector<FMenuItem*>::const_iterator next_element;
|
||||
|
||||
next_element = iter;
|
||||
do
|
||||
{
|
||||
++next_element;
|
||||
if ( next_element == itemlist.end() )
|
||||
next_element = itemlist.begin();
|
||||
next = static_cast<FMenuItem*>(*next_element);
|
||||
} while ( ! next->isEnabled()
|
||||
|| ! next->acceptFocus()
|
||||
|| ! next->isVisible()
|
||||
|| next->isSeparator() );
|
||||
if ( next == *iter )
|
||||
return false;
|
||||
unselectItemInMenu();
|
||||
next->setSelected();
|
||||
next->setFocus();
|
||||
if ( next->hasMenu() )
|
||||
{
|
||||
FMenuItem* first_item;
|
||||
FMenu* menu = next->getMenu();
|
||||
menu->selectFirstItemInList();
|
||||
first_item = menu->getSelectedListItem();
|
||||
if ( first_item )
|
||||
first_item->setFocus();
|
||||
menu->redraw();
|
||||
}
|
||||
if ( statusBar() )
|
||||
statusBar()->drawMessage();
|
||||
selectedMenuItem = next;
|
||||
redraw();
|
||||
break;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool FMenuBar::selectPrevItem()
|
||||
{
|
||||
std::vector<FMenuItem*>::const_iterator iter, begin;
|
||||
iter = itemlist.end();
|
||||
begin = itemlist.begin();
|
||||
|
||||
do
|
||||
{
|
||||
--iter;
|
||||
if ( (*iter)->isSelected() )
|
||||
{
|
||||
FMenuItem* prev;
|
||||
std::vector<FMenuItem*>::const_iterator prev_element;
|
||||
|
||||
prev_element = iter;
|
||||
do
|
||||
{
|
||||
if ( prev_element == itemlist.begin() )
|
||||
prev_element = itemlist.end();
|
||||
--prev_element;
|
||||
prev = static_cast<FMenuItem*>(*prev_element);
|
||||
} while ( ! prev->isEnabled()
|
||||
|| ! prev->acceptFocus()
|
||||
|| ! prev->isVisible()
|
||||
|| prev->isSeparator() );
|
||||
if ( prev == *iter )
|
||||
return false;
|
||||
unselectItemInMenu();
|
||||
prev->setSelected();
|
||||
prev->setFocus();
|
||||
if ( prev->hasMenu() )
|
||||
{
|
||||
FMenuItem* first_item;
|
||||
FMenu* menu = prev->getMenu();
|
||||
menu->selectFirstItemInList();
|
||||
first_item = menu->getSelectedListItem();
|
||||
if ( first_item )
|
||||
first_item->setFocus();
|
||||
menu->redraw();
|
||||
}
|
||||
if ( statusBar() )
|
||||
statusBar()->drawMessage();
|
||||
selectedMenuItem = prev;
|
||||
redraw();
|
||||
break;
|
||||
}
|
||||
} while ( iter != begin );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int FMenuBar::getHotkeyPos (wchar_t*& src, wchar_t*& dest, uInt length)
|
||||
{
|
||||
|
@ -147,16 +251,17 @@ void FMenuBar::drawItems()
|
|||
wchar_t* item_text;
|
||||
FString txt;
|
||||
uInt txt_length;
|
||||
int hotkeypos, to_char;
|
||||
bool is_Active, is_Selected, is_NoUnderline;
|
||||
int hotkeypos, startpos, to_char;
|
||||
bool is_active, is_selected, is_noUnderline;
|
||||
|
||||
is_Active = (*iter)->isEnabled();
|
||||
is_Selected = (*iter)->isSelected();
|
||||
is_NoUnderline = (((*iter)->getFlags() & NO_UNDERLINE) != 0);
|
||||
startpos = x + 1;
|
||||
is_active = (*iter)->isEnabled();
|
||||
is_selected = (*iter)->isSelected();
|
||||
is_noUnderline = (((*iter)->getFlags() & NO_UNDERLINE) != 0);
|
||||
|
||||
if ( is_Active )
|
||||
if ( is_active )
|
||||
{
|
||||
if ( is_Selected )
|
||||
if ( is_selected )
|
||||
{
|
||||
if ( isMonochron() )
|
||||
setReverse(false);
|
||||
|
@ -175,8 +280,12 @@ void FMenuBar::drawItems()
|
|||
backgroundColor = wc.menu_inactive_bg;
|
||||
}
|
||||
setColor (foregroundColor, backgroundColor);
|
||||
|
||||
if ( x < screenWidth )
|
||||
{
|
||||
x++;
|
||||
print (vmenubar, ' ');
|
||||
}
|
||||
|
||||
txt = (*iter)->getText();
|
||||
txt_length = uInt(txt.getLength());
|
||||
|
@ -196,10 +305,13 @@ void FMenuBar::drawItems()
|
|||
txt_length--;
|
||||
to_char--;
|
||||
}
|
||||
|
||||
x += int(txt_length);
|
||||
|
||||
for (int z=0; z < to_char; z++)
|
||||
{
|
||||
if ( startpos > screenWidth-z )
|
||||
break;
|
||||
if ( ! iswprint(wint_t(item_text[z])) )
|
||||
{
|
||||
if ( ! isNewFont() && ( int(item_text[z]) < fc::NF_rev_left_arrow2
|
||||
|
@ -208,13 +320,13 @@ void FMenuBar::drawItems()
|
|||
item_text[z] = L' ';
|
||||
}
|
||||
}
|
||||
if ( (z == hotkeypos) && is_Active && ! is_Selected )
|
||||
if ( (z == hotkeypos) && is_active && ! is_selected )
|
||||
{
|
||||
setColor (wc.menu_hotkey_fg, wc.menu_hotkey_bg);
|
||||
if ( ! is_NoUnderline )
|
||||
if ( ! is_noUnderline )
|
||||
setUnderline();
|
||||
print (vmenubar, item_text[z]);
|
||||
if ( ! is_NoUnderline )
|
||||
if ( ! is_noUnderline )
|
||||
unsetUnderline();
|
||||
setColor (foregroundColor, backgroundColor);
|
||||
}
|
||||
|
@ -222,19 +334,28 @@ void FMenuBar::drawItems()
|
|||
print (vmenubar, item_text[z]);
|
||||
}
|
||||
|
||||
if ( x > screenWidth )
|
||||
if ( x > screenWidth+1 )
|
||||
{
|
||||
print (vmenubar, txt.left(uInt(int(txt_length)+screenWidth-x-1)));
|
||||
if ( startpos < screenWidth )
|
||||
{
|
||||
gotoxy(screenWidth-1,1);
|
||||
print (vmenubar, "..");
|
||||
}
|
||||
else
|
||||
else if ( startpos-2 < screenWidth )
|
||||
{
|
||||
gotoxy(screenWidth,1);
|
||||
print (vmenubar, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
if ( x < screenWidth )
|
||||
{
|
||||
x++;
|
||||
print (vmenubar, ' ');
|
||||
}
|
||||
|
||||
setColor (wc.menu_active_fg, wc.menu_active_bg);
|
||||
if ( isMonochron() && is_Active && is_Selected )
|
||||
if ( isMonochron() && is_active && is_selected )
|
||||
setReverse(true);
|
||||
delete[] item_text;
|
||||
|
||||
|
@ -248,6 +369,17 @@ void FMenuBar::drawItems()
|
|||
setReverse(false);
|
||||
|
||||
setUpdateVTerm(true);
|
||||
/*
|
||||
if ( hasSelectedMenuItem() && statusBar() )
|
||||
{
|
||||
FString msg = getSelectedMenuItem()->getStatusbarMessage();
|
||||
FString curMsg = statusBar()->getMessage();
|
||||
if ( curMsg != msg )
|
||||
{
|
||||
statusBar()->setMessage(msg);
|
||||
statusBar()->drawMessage();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -267,13 +399,34 @@ void FMenuBar::onKeyPress (FKeyEvent* ev)
|
|||
{
|
||||
switch ( ev->key() )
|
||||
{
|
||||
case fc::Fkey_return:
|
||||
case fc::Fkey_enter:
|
||||
if ( hasSelectedMenuItem() )
|
||||
{
|
||||
FMenuItem* sel_menu = getSelectedMenuItem();
|
||||
if ( ! sel_menu->hasMenu() )
|
||||
{
|
||||
sel_menu->unsetSelected();
|
||||
selectedMenuItem = 0;
|
||||
redraw();
|
||||
sel_menu->processClicked();
|
||||
}
|
||||
}
|
||||
ev->accept();
|
||||
break;
|
||||
|
||||
case fc::Fkey_up: // avoid focusNextChild() or focusPrevChild()
|
||||
case fc::Fkey_down:
|
||||
ev->accept();
|
||||
break;
|
||||
|
||||
case fc::Fkey_left:
|
||||
beep();
|
||||
selectPrevItem();
|
||||
ev->accept();
|
||||
break;
|
||||
|
||||
case fc::Fkey_right:
|
||||
beep();
|
||||
selectNextItem();
|
||||
ev->accept();
|
||||
break;
|
||||
|
||||
|
@ -288,22 +441,11 @@ void FMenuBar::onMouseDown (FMouseEvent* ev)
|
|||
if ( ev->getButton() != LeftButton )
|
||||
{
|
||||
mouse_down = false;
|
||||
|
||||
if ( ! itemlist.empty() )
|
||||
{
|
||||
std::vector<FMenuItem*>::const_iterator iter, end;
|
||||
iter = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
|
||||
while ( iter != end )
|
||||
{
|
||||
(*iter)->unsetSelected();
|
||||
if ( selectedMenuItem == *iter )
|
||||
selectedMenuItem = 0;
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
unselectItemInMenu();
|
||||
redraw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -340,10 +482,17 @@ void FMenuBar::onMouseDown (FMouseEvent* ev)
|
|||
{
|
||||
if ( (*iter)->isEnabled() && ! (*iter)->isSelected() )
|
||||
{
|
||||
FWidget* focused_widget = getFocusWidget();
|
||||
FFocusEvent out (FocusOut_Event);
|
||||
FApplication::queueEvent(focused_widget, &out);
|
||||
(*iter)->setSelected();
|
||||
//FMessageBox::info (this, "Info", (*iter)->getStatusbarMessage());
|
||||
(*iter)->setFocus();
|
||||
//FMessageBox::info (this, "Info", statusBar()->getMessage());
|
||||
selectedMenuItem = *iter;
|
||||
focus_changed = true;
|
||||
if ( focused_widget )
|
||||
focused_widget->redraw();
|
||||
}
|
||||
if ( (*iter)->hasMenu() )
|
||||
{
|
||||
|
@ -351,9 +500,12 @@ void FMenuBar::onMouseDown (FMouseEvent* ev)
|
|||
if ( menu->hasSelectedListItem() )
|
||||
{
|
||||
menu->unselectItemInList();
|
||||
(*iter)->setFocus();
|
||||
menu->redraw();
|
||||
focus_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -369,6 +521,8 @@ void FMenuBar::onMouseDown (FMouseEvent* ev)
|
|||
}
|
||||
++iter;
|
||||
}
|
||||
if ( statusBar() )
|
||||
statusBar()->drawMessage();
|
||||
if ( focus_changed )
|
||||
redraw();
|
||||
}
|
||||
|
@ -411,9 +565,15 @@ void FMenuBar::onMouseUp (FMouseEvent* ev)
|
|||
FMenu* menu = (*iter)->getMenu();
|
||||
if ( ! menu->hasSelectedListItem() )
|
||||
{
|
||||
FMenuItem* first_item;
|
||||
menu->selectFirstItemInList();
|
||||
menu->getSelectedListItem()->setFocus();
|
||||
first_item = menu->getSelectedListItem();
|
||||
if ( first_item )
|
||||
first_item->setFocus();
|
||||
menu->redraw();
|
||||
if ( statusBar() )
|
||||
statusBar()->drawMessage();
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -464,11 +624,16 @@ void FMenuBar::onMouseMove (FMouseEvent* ev)
|
|||
{
|
||||
if ( (*iter)->isEnabled() && ! (*iter)->isSelected() )
|
||||
{
|
||||
FWidget* focused_widget = getFocusWidget();
|
||||
FFocusEvent out (FocusOut_Event);
|
||||
FApplication::queueEvent(focused_widget, &out);
|
||||
(*iter)->setSelected();
|
||||
(*iter)->setFocus();
|
||||
selectedMenuItem = *iter;
|
||||
focus_changed = true;
|
||||
}
|
||||
if ( focused_widget )
|
||||
focused_widget->redraw();
|
||||
|
||||
if ( (*iter)->hasMenu() )
|
||||
{
|
||||
FMenu* menu = (*iter)->getMenu();
|
||||
|
@ -479,6 +644,9 @@ void FMenuBar::onMouseMove (FMouseEvent* ev)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if ( statusBar() )
|
||||
statusBar()->clearMessage();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( getGeometryGlobal().contains(ev->getGlobalPos())
|
||||
|
@ -492,6 +660,7 @@ void FMenuBar::onMouseMove (FMouseEvent* ev)
|
|||
}
|
||||
else if ( hasSelectedMenuItem() && selectedMenuItem->hasMenu() )
|
||||
{
|
||||
// Mouse event handover to the menu
|
||||
FMenu* menu = selectedMenuItem->getMenu();
|
||||
const FRect& menu_geometry = menu->getGeometryGlobal();
|
||||
|
||||
|
@ -508,6 +677,8 @@ void FMenuBar::onMouseMove (FMouseEvent* ev)
|
|||
}
|
||||
++iter;
|
||||
}
|
||||
if ( statusBar() )
|
||||
statusBar()->drawMessage();
|
||||
if ( focus_changed )
|
||||
redraw();
|
||||
}
|
||||
|
@ -535,6 +706,14 @@ void FMenuBar::hide()
|
|||
delete[] blank;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FMenuBar::unselectItemInMenu()
|
||||
{
|
||||
if ( hasSelectedMenuItem() )
|
||||
selectedMenuItem->unsetSelected();
|
||||
selectedMenuItem = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FMenuBar::setGeometry (int xx, int yy, int ww, int hh, bool adjust)
|
||||
{
|
||||
|
|
|
@ -54,6 +54,8 @@ class FMenuBar : public FWindow, public FMenuList
|
|||
void init();
|
||||
void menu_dimension();
|
||||
bool isMenu (FMenuItem*) const;
|
||||
bool selectNextItem();
|
||||
bool selectPrevItem();
|
||||
int getHotkeyPos (wchar_t*&, wchar_t*&, uInt);
|
||||
void draw();
|
||||
void drawItems();
|
||||
|
@ -69,6 +71,8 @@ class FMenuBar : public FWindow, public FMenuList
|
|||
void onMouseUp (FMouseEvent*);
|
||||
void onMouseMove (FMouseEvent*);
|
||||
void hide();
|
||||
void unselectItemInMenu();
|
||||
FMenuItem* getSelectedMenuItem() const;
|
||||
bool hasSelectedMenuItem() const;
|
||||
// make every setGeometry from FWidget available
|
||||
using FWidget::setGeometry;
|
||||
|
@ -88,6 +92,10 @@ class FMenuBar : public FWindow, public FMenuList
|
|||
inline const char* FMenuBar::getClassName() const
|
||||
{ return "FMenuBar"; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline FMenuItem* FMenuBar::getSelectedMenuItem() const
|
||||
{ return selectedMenuItem; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool FMenuBar::hasSelectedMenuItem() const
|
||||
{ return selectedMenuItem; }
|
||||
|
|
|
@ -87,7 +87,7 @@ FMenuItem::~FMenuItem() // destructor
|
|||
void FMenuItem::init (FWidget* parent)
|
||||
{
|
||||
text_length = text.getLength();
|
||||
hotkey = getHotkey();
|
||||
hotkey = hotKey();
|
||||
if ( hotkey )
|
||||
text_length--;
|
||||
setGeometry (1,1,int(text_length+2),1, false);
|
||||
|
@ -147,7 +147,7 @@ void FMenuItem::init (FWidget* parent)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
uChar FMenuItem::getHotkey()
|
||||
uChar FMenuItem::hotKey()
|
||||
{
|
||||
uInt length;
|
||||
|
||||
|
@ -338,14 +338,17 @@ void FMenuItem::onAccel (FAccelEvent* ev)
|
|||
FMenuBar* mb = dynamic_cast<FMenuBar*>(super_menu);
|
||||
if ( mb )
|
||||
{
|
||||
if ( mb->selectedMenuItem )
|
||||
mb->selectedMenuItem->unsetSelected();
|
||||
setSelected();
|
||||
mb->selectedMenuItem = this;
|
||||
mb->redraw();
|
||||
if ( menu && ! menu->hasSelectedListItem() )
|
||||
{
|
||||
FWidget* focused_widget = static_cast<FWidget*>(ev->focusedWidget());
|
||||
FWidget* focused_widget;
|
||||
|
||||
if ( mb->getSelectedMenuItem() )
|
||||
mb->getSelectedMenuItem()->unsetSelected();
|
||||
setSelected();
|
||||
mb->selectedMenuItem = this;
|
||||
|
||||
|
||||
focused_widget = static_cast<FWidget*>(ev->focusedWidget());
|
||||
FFocusEvent out (FocusOut_Event);
|
||||
FApplication::queueEvent(focused_widget, &out);
|
||||
menu->selectFirstItemInList();
|
||||
|
@ -355,6 +358,14 @@ void FMenuItem::onAccel (FAccelEvent* ev)
|
|||
menu->redraw();
|
||||
if ( statusBar() )
|
||||
statusBar()->drawMessage();
|
||||
mb->redraw();
|
||||
}
|
||||
else
|
||||
{
|
||||
unsetSelected();
|
||||
mb->selectedMenuItem = 0;
|
||||
mb->redraw();
|
||||
processClicked();
|
||||
}
|
||||
ev->accept();
|
||||
}
|
||||
|
@ -417,13 +428,13 @@ bool FMenuItem::setFocus (bool on)
|
|||
|
||||
if ( isEnabled() )
|
||||
{
|
||||
/*if ( statusBar() )
|
||||
if ( statusBar() )
|
||||
{
|
||||
FString msg = getStatusbarMessage();
|
||||
FString curMsg = statusBar()->getMessage();
|
||||
if ( curMsg != msg )
|
||||
statusBar()->setMessage(msg);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -458,7 +469,7 @@ void FMenuItem::setText (FString& txt)
|
|||
{
|
||||
text = txt;
|
||||
text_length = text.getLength();
|
||||
hotkey = getHotkey();
|
||||
hotkey = hotKey();
|
||||
if ( hotkey )
|
||||
text_length--;
|
||||
setWidth(int(text_length));
|
||||
|
|
|
@ -57,7 +57,7 @@ class FMenuItem : public FWidget
|
|||
FMenuItem (const FMenuItem&);
|
||||
FMenuItem& operator = (const FMenuItem&);
|
||||
void init (FWidget*);
|
||||
uChar getHotkey();
|
||||
uChar hotKey();
|
||||
bool isMenuBar (FWidget*) const;
|
||||
bool isMenu (FWidget*) const;
|
||||
FWidget* getSuperMenu() const;
|
||||
|
@ -96,6 +96,7 @@ class FMenuItem : public FWidget
|
|||
void setChecked();
|
||||
void unsetChecked();
|
||||
bool isChecked() const;
|
||||
int getHotkey() const;
|
||||
bool hasHotkey() const;
|
||||
FMenu* getMenu() const;
|
||||
void setMenu(FMenu*);
|
||||
|
@ -162,6 +163,10 @@ inline void FMenuItem::unsetChecked()
|
|||
inline bool FMenuItem::isChecked() const
|
||||
{ return checked; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline int FMenuItem::getHotkey() const
|
||||
{ return hotkey; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool FMenuItem::hasHotkey() const
|
||||
{ return bool(hotkey != 0); }
|
||||
|
|
|
@ -25,7 +25,6 @@ FMenuList::~FMenuList() // destructor
|
|||
while ( iter != itemlist.end() )
|
||||
{
|
||||
(*iter)->setSuperMenu(0);
|
||||
//delAccelerator (*iter);
|
||||
iter = itemlist.erase(iter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1554,6 +1554,7 @@ void FTerm::init()
|
|||
setPalette (fc::DarkGray, 0x50, 0x50, 0x50);
|
||||
setPalette (fc::LightBlue, 0x80, 0xa4, 0xec);
|
||||
setPalette (fc::LightGreen, 0xd4, 0xd4, 0xd4);
|
||||
setPalette (fc::LightCyan, 0x49, 0xc9, 0xe3);
|
||||
setPalette (fc::LightRed, 0xff, 0x54, 0x54);
|
||||
setPalette (fc::Yellow, 0xff, 0xff, 0x54);
|
||||
setPalette (fc::White, 0xff, 0xff, 0xff);
|
||||
|
|
|
@ -964,6 +964,12 @@ FMenuBar* FWidget::menuBar()
|
|||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FWidget::setStatusbarMessage (FString msg)
|
||||
{
|
||||
statusbar_message = msg;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void FWidget::addCallback ( FString cb_signal
|
||||
, FWidget::FCallback cb_handler
|
||||
|
|
|
@ -343,7 +343,7 @@ class FWidget : public FObject, public FTerm
|
|||
|
||||
static FStatusBar* statusBar();
|
||||
static FMenuBar* menuBar();
|
||||
void setStatusbarMessage (FString);
|
||||
virtual void setStatusbarMessage (FString);
|
||||
void clearStatusbarMessage();
|
||||
FString getStatusbarMessage();
|
||||
|
||||
|
@ -501,10 +501,6 @@ inline FWidget* FWidget::parentWidget() const
|
|||
inline bool FWidget::isRootWidget() const
|
||||
{ return (! hasParent()); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline void FWidget::setStatusbarMessage(FString msg)
|
||||
{ statusbar_message = msg; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline void FWidget::clearStatusbarMessage()
|
||||
{ statusbar_message.clear(); }
|
||||
|
|
53
test/ui.cpp
53
test/ui.cpp
|
@ -192,33 +192,53 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
: FDialog(parent)
|
||||
, myList()
|
||||
{
|
||||
/* .--------------------------------------------. */
|
||||
/* v This Code is working in progress v */
|
||||
|
||||
// menu bar
|
||||
FMenuBar* Menubar = new FMenuBar(this);
|
||||
|
||||
// menu bar items
|
||||
FMenu* File = new FMenu("&File", Menubar);
|
||||
File->setStatusbarMessage("File management commands");
|
||||
FMenu* Edit = new FMenu("&Edit", Menubar);
|
||||
Edit->setStatusbarMessage("Cut-and-paste editing commands");
|
||||
FMenu* View = new FMenu("&View", Menubar);
|
||||
View->setStatusbarMessage("Show internal informations");
|
||||
FMenuItem* Options = new FMenuItem("&Options", Menubar);
|
||||
Options->setStatusbarMessage("Set program defaults");
|
||||
Options->setDisable();
|
||||
FMenuItem* Help = new FMenuItem("&Help", Menubar);
|
||||
Help->setStatusbarMessage("Show version and copyright information");
|
||||
|
||||
// "File" menu items
|
||||
FMenuItem* Open = new FMenuItem("&Open...", File);
|
||||
Open->setStatusbarMessage("Locate and open a text file");
|
||||
FMenuItem* Line = new FMenuItem(File);
|
||||
Line->setSeparator();
|
||||
FMenuItem* Line1 = new FMenuItem(File);
|
||||
Line1->setSeparator();
|
||||
FMenuItem* Quit = new FMenuItem("&Quit", File);
|
||||
Quit->setStatusbarMessage("Exit the program");
|
||||
|
||||
// "Edit" menu items
|
||||
FMenuItem* Undo = new FMenuItem("Undo", Edit);
|
||||
Undo->setDisable();
|
||||
FMenuItem* Redo = new FMenuItem("Redo", Edit);
|
||||
Redo->setDisable();
|
||||
FMenuItem* Line2 = new FMenuItem(Edit);
|
||||
Line2->setSeparator();
|
||||
FMenuItem* Cut = new FMenuItem("Cu&t", Edit);
|
||||
Cut->setStatusbarMessage("Remove the input text and put it in the clipboard");
|
||||
FMenuItem* Copy = new FMenuItem("&Copy", Edit);
|
||||
Copy->setStatusbarMessage("Copy the input text into the clipboad");
|
||||
FMenuItem* Paste = new FMenuItem("&Paste", Edit);
|
||||
Paste->setStatusbarMessage("Insert text form clipboard");
|
||||
FMenuItem* Clear = new FMenuItem("C&lear", Edit);
|
||||
Clear->setStatusbarMessage("Delete input text");
|
||||
|
||||
// "View" menu items
|
||||
FMenuItem* Env = new FMenuItem("&Terminal info...", View);
|
||||
Env->setStatusbarMessage("Informations about this terminal");
|
||||
FMenuItem* Drive = new FMenuItem("&Drive symbols...", View);
|
||||
Drive->setStatusbarMessage("Show drive symbols");
|
||||
|
||||
// Menu function callbacks
|
||||
Open->addCallback
|
||||
(
|
||||
"clicked",
|
||||
|
@ -244,6 +264,11 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
"clicked",
|
||||
_METHOD_CALLBACK (this, &MyDialog::cb_noFunctionMsg)
|
||||
);
|
||||
Clear->addCallback
|
||||
(
|
||||
"clicked",
|
||||
_METHOD_CALLBACK (this, &MyDialog::cb_noFunctionMsg)
|
||||
);
|
||||
Env->addCallback
|
||||
(
|
||||
"clicked",
|
||||
|
@ -254,20 +279,13 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
"clicked",
|
||||
_METHOD_CALLBACK (this, &MyDialog::cb_drives)
|
||||
);
|
||||
Options->addCallback
|
||||
(
|
||||
"clicked",
|
||||
_METHOD_CALLBACK (this, &MyDialog::cb_exitApp)
|
||||
);
|
||||
Help->addCallback
|
||||
(
|
||||
"clicked",
|
||||
_METHOD_CALLBACK (this, &MyDialog::cb_about)
|
||||
);
|
||||
|
||||
/* ^ This Code is working in progress ^ */
|
||||
/* '--------------------------------------------' */
|
||||
|
||||
// Buttons
|
||||
FButton* MyButton1 = new FButton(this);
|
||||
MyButton1->setGeometry(3, 3, 5, 1);
|
||||
MyButton1->setText(L"&SIN");
|
||||
|
@ -291,6 +309,7 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
MyButton3->setNoUnderline();
|
||||
MyButton3->setFlat();
|
||||
|
||||
// Radio buttons in a group
|
||||
FButtonGroup* radioButtonGroup = new FButtonGroup("Button", this);
|
||||
radioButtonGroup->setGeometry(3, 8, 14, 4);
|
||||
//radioButtonGroup->unsetBorder();
|
||||
|
@ -306,6 +325,7 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
radio2->setChecked();
|
||||
//radio2->setDisable();
|
||||
|
||||
// Checkboxes in a group
|
||||
FButtonGroup* checkButtonGroup = new FButtonGroup("Options", this);
|
||||
checkButtonGroup->setGeometry(3, 12, 14, 4);
|
||||
|
||||
|
@ -318,6 +338,7 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
check2->setChecked();
|
||||
check2->setNoUnderline();
|
||||
|
||||
// A text input field
|
||||
FLineEdit* MyLineEdit = new FLineEdit(this);
|
||||
MyLineEdit->setGeometry(22, 1, 10, 1);
|
||||
MyLineEdit->setText( FString("EnTry").toLower());
|
||||
|
@ -325,6 +346,7 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
MyLineEdit->setStatusbarMessage("Press Enter to set the title");
|
||||
MyLineEdit->setShadow();
|
||||
|
||||
// Buttons
|
||||
FButton* MyButton4 = new FButton(this);
|
||||
MyButton4->setGeometry(20, 8, 12, 1);
|
||||
MyButton4->setText(L"&Get input");
|
||||
|
@ -346,6 +368,7 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
MyButton6->setShadow();
|
||||
MyButton6->addAccelerator('x');
|
||||
|
||||
// A multiple selection listbox
|
||||
myList = new FListBox(this);
|
||||
myList->setGeometry(38, 1, 14, 17);
|
||||
myList->setText("Items");
|
||||
|
@ -354,6 +377,7 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
for (int z=1; z < 100; z++)
|
||||
myList->insert( FString().setNumber(z) + L" placeholder" );
|
||||
|
||||
// Text labels
|
||||
FLabel* headline = new FLabel(this);
|
||||
headline->setGeometry(21, 3, 10, 1);
|
||||
headline->setText(L"List items");
|
||||
|
@ -375,11 +399,14 @@ MyDialog::MyDialog (FWidget* parent)
|
|||
sum_count->setGeometry(29, 5, 5, 3);
|
||||
sum_count->setNumber(myList->count());
|
||||
|
||||
// Statusbar at the bottom
|
||||
FStatusBar* statusbar = new FStatusBar(this);
|
||||
// Statusbar keys
|
||||
FStatusKey* key_F1 = new FStatusKey(fc::Fkey_f1, "About", statusbar);
|
||||
FStatusKey* key_F2 = new FStatusKey(fc::Fkey_f2, "View", statusbar);
|
||||
FStatusKey* key_F3 = new FStatusKey(fc::Fkey_f3, "Quit", statusbar);
|
||||
|
||||
// Add some function callbacks
|
||||
MyButton1->addCallback
|
||||
(
|
||||
"clicked",
|
||||
|
|
Loading…
Reference in New Issue