Add a title bar menu to close dialogs

This commit is contained in:
Markus Gans 2016-06-12 23:06:58 +02:00
parent 29dfeafa87
commit b576b8dcad
10 changed files with 268 additions and 30 deletions

View File

@ -1,3 +1,6 @@
2016-06-12 Markus Gans <guru.mail@muenster.de>
* Add a title bar menu to close dialogs
2016-05-24 Markus Gans <guru.mail@muenster.de> 2016-05-24 Markus Gans <guru.mail@muenster.de>
* Use nl_langinfo to determine the numeric thousands separator * Use nl_langinfo to determine the numeric thousands separator
for Fstring::setFormatedNumber as default parameter for Fstring::setFormatedNumber as default parameter

View File

@ -20,8 +20,6 @@ Missing Features
└──► tmp └──► tmp
--------------------------------------- ---------------------------------------
- A single click on the FDialog title button [-] should open
a FMenu with a closing item
- FDialog title button [▲] and [▼] should maximized or restore - FDialog title button [▲] and [▼] should maximized or restore
the window size on a resizeable dialog the window size on a resizeable dialog
- A possibility to change the window size dynamically with the mouse - A possibility to change the window size dynamically with the mouse

View File

@ -969,7 +969,7 @@ void FApplication::processMouseEvent()
} }
} }
// close open menu // close the open menu
if ( open_menu && ! b_state.mouse_moved ) if ( open_menu && ! b_state.mouse_moved )
{ {
FMenu* menu = static_cast<FMenu*>(open_menu); FMenu* menu = static_cast<FMenu*>(open_menu);
@ -980,8 +980,6 @@ void FApplication::processMouseEvent()
menu->hide(); menu->hide();
menu->hideSubMenus(); menu->hideSubMenus();
menu->hideSuperMenus(); menu->hideSuperMenus();
if ( statusBar() )
statusBar()->clearMessage();
// No widget was been clicked // No widget was been clicked
if ( ! clicked_widget ) if ( ! clicked_widget )
@ -1375,7 +1373,9 @@ bool FApplication::sendEvent(FObject* receiver, FEvent* event)
window = FWindow::getWindowWidget(widget); window = FWindow::getWindowWidget(widget);
// block events for widgets in non modal windows // block events for widgets in non modal windows
if ( window && (window->getFlags() & fc::modal) == 0 ) if ( window
&& (window->getFlags() & fc::modal) == 0
&& ! window->isMenu() )
{ {
switch ( event->type() ) switch ( event->type() )
{ {

View File

@ -20,6 +20,8 @@ FDialog::FDialog(FWidget* parent)
, TitleBarClickPos() , TitleBarClickPos()
, oldGeometry() , oldGeometry()
, focus_widget(0) , focus_widget(0)
, dialog_menu()
, dgl_menuitem()
{ {
init(); init();
} }
@ -33,6 +35,8 @@ FDialog::FDialog (const FString& txt, FWidget* parent)
, TitleBarClickPos() , TitleBarClickPos()
, oldGeometry() , oldGeometry()
, focus_widget(0) , focus_widget(0)
, dialog_menu()
, dgl_menuitem()
{ {
init(); init();
} }
@ -88,12 +92,13 @@ FDialog::~FDialog() // destructor
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FDialog::init() void FDialog::init()
{ {
FWidget* rootObj = getRootWidget();
xmin = 1 + rootObj->getLeftPadding();
ymin = 1 + rootObj->getTopPadding();
xmax = rootObj->getWidth();
ymax = rootObj->getHeight();
width = 10; width = 10;
height = 10; height = 10;
xmin = 1;
ymin = 1;
xmax = width;
ymax = height;
client_xmin = 1; client_xmin = 1;
client_ymin = 1; client_ymin = 1;
client_xmax = width; client_xmax = width;
@ -106,6 +111,7 @@ void FDialog::init()
setGeometry (1, 1, 10, 10, false); // initialize geometry values setGeometry (1, 1, 10, 10, false); // initialize geometry values
ignore_padding = true; ignore_padding = true;
window_object = true; window_object = true;
dialog_object = true;
addWindow(this); addWindow(this);
setActiveWindow(this); setActiveWindow(this);
@ -124,6 +130,25 @@ void FDialog::init()
old_focus->redraw(); old_focus->redraw();
} }
accelerator_list = new Accelerators(); accelerator_list = new Accelerators();
dialog_menu = new FMenu ("-", this);
dialog_menu->move (xpos, ypos+1);
dgl_menuitem = dialog_menu->getItem();
if ( dgl_menuitem )
{
dgl_menuitem->ignorePadding();
dgl_menuitem->unsetFocusable();
}
FMenuItem* close_item = new FMenuItem ("&Close", dialog_menu);
close_item->setStatusbarMessage ("Close window");
close_item->addCallback
(
"clicked",
_METHOD_CALLBACK (this, &FDialog::cb_close)
);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -214,14 +239,28 @@ void FDialog::drawTitleBar()
print (fc::NF_rev_menu_button3); print (fc::NF_rev_menu_button3);
} }
else if ( isMonochron() ) else if ( isMonochron() )
print ("[-]"); {
print ('[');
if ( dgl_menuitem )
print (dgl_menuitem->getText());
else else
print (" - "); print ('-');
print (']');
}
else
{
print (' ');
if ( dgl_menuitem )
print (dgl_menuitem->getText());
else
print ('-');
print (' ');
}
// fill with spaces (left of the title) // fill with spaces (left of the title)
if ( getMaxColor() < 16 ) if ( getMaxColor() < 16 )
setBold(); setBold();
if ( isActiveWindow() ) if ( isActiveWindow() || dialog_menu->isVisible() )
setColor (wc.titlebar_active_fg, wc.titlebar_active_bg); setColor (wc.titlebar_active_fg, wc.titlebar_active_bg);
else else
setColor (wc.titlebar_inactive_fg, wc.titlebar_inactive_bg); setColor (wc.titlebar_inactive_fg, wc.titlebar_inactive_bg);
@ -251,6 +290,17 @@ void FDialog::drawTitleBar()
} }
//----------------------------------------------------------------------
void FDialog::cb_close (FWidget*, void*)
{
dialog_menu->unselectItem();
dialog_menu->hide();
setClickedWidget(0);
drawTitleBar();
close();
}
// protected methods of FDialog // protected methods of FDialog
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FDialog::done(int result) void FDialog::done(int result)
@ -475,6 +525,47 @@ void FDialog::onMouseDown (FMouseEvent* ev)
} }
if ( has_raised ) if ( has_raised )
redraw(); redraw();
// click on titlebar menu button
if ( mouse_x < 4 && mouse_y == 1 )
{
if ( dialog_menu->isVisible() )
{
dialog_menu->unselectItem();
dialog_menu->hide();
activateWindow();
raiseWindow();
getFocusWidget()->setFocus();
redraw();
if ( statusBar() )
statusBar()->drawMessage();
}
else
{
setOpenMenu(dialog_menu);
dialog_menu->move (xpos, ypos+1);
dialog_menu->setVisible();
dialog_menu->show();
dialog_menu->raiseWindow(dialog_menu);
dialog_menu->redraw();
}
}
}
else // ev->getButton() != fc::LeftButton
{
// click on titlebar menu button
if ( mouse_x < 4 && mouse_y == 1 && dialog_menu->isVisible() )
{
// close menu
dialog_menu->unselectItem();
dialog_menu->hide();
activateWindow();
raiseWindow();
getFocusWidget()->setFocus();
redraw();
if ( statusBar() )
statusBar()->drawMessage();
}
} }
if ( ev->getButton() == fc::RightButton ) if ( ev->getButton() == fc::RightButton )
@ -537,6 +628,9 @@ void FDialog::onMouseUp (FMouseEvent* ev)
if ( ev->getButton() == fc::LeftButton ) if ( ev->getButton() == fc::LeftButton )
{ {
int mouse_x = ev->getX();
int mouse_y = ev->getY();
if ( ! TitleBarClickPos.isNull() if ( ! TitleBarClickPos.isNull()
&& titlebar_x > xpos+xmin+2 && titlebar_x > xpos+xmin+2
&& titlebar_x < xpos+xmin+width && titlebar_x < xpos+xmin+width
@ -547,6 +641,24 @@ void FDialog::onMouseUp (FMouseEvent* ev)
move (currentPos + deltaPos); move (currentPos + deltaPos);
TitleBarClickPos = ev->getGlobalPos(); TitleBarClickPos = ev->getGlobalPos();
} }
// click on titlebar menu button
if ( mouse_x < 4
&& mouse_y == 1
&& dialog_menu->isVisible()
&& ! dialog_menu->hasSelectedItem() )
{
FMenuItem* first_item;
dialog_menu->selectFirstItem();
first_item = dialog_menu->getSelectedItem();
if ( first_item )
first_item->setFocus();
dialog_menu->redraw();
if ( statusBar() )
statusBar()->drawMessage();
updateTerminal();
flush_out();
}
} }
} }
@ -562,6 +674,25 @@ void FDialog::onMouseMove (FMouseEvent* ev)
move (currentPos + deltaPos); move (currentPos + deltaPos);
TitleBarClickPos = ev->getGlobalPos(); TitleBarClickPos = ev->getGlobalPos();
} }
if ( dialog_menu->isVisible() && dialog_menu->isShown() )
{
// Mouse event handover to the menu
const FRect& menu_geometry = dialog_menu->getGeometryGlobal();
if ( dialog_menu->count() > 0
&& menu_geometry.contains(ev->getGlobalPos()) )
{
const FPoint& g = ev->getGlobalPos();
const FPoint& p = dialog_menu->globalToLocalPos(g);
int b = ev->getButton();
FMouseEvent* _ev = new FMouseEvent (fc::MouseMove_Event, p, g, b);
dialog_menu->mouse_down = true;
setClickedWidget(dialog_menu);
dialog_menu->onMouseMove(_ev);
delete _ev;
}
}
} }
} }
@ -580,7 +711,13 @@ void FDialog::onMouseDoubleClick (FMouseEvent* ev)
FPoint gPos = ev->getGlobalPos(); FPoint gPos = ev->getGlobalPos();
if ( title_button.contains(gPos) ) if ( title_button.contains(gPos) )
{ {
dialog_menu->unselectItem();
dialog_menu->hide();
setClickedWidget(0); setClickedWidget(0);
if ( isModal() )
done(FDialog::Reject);
else
close(); close();
} }
} }
@ -591,8 +728,6 @@ void FDialog::onWindowActive (FEvent*)
if ( isVisible() && isShown() ) if ( isVisible() && isShown() )
drawTitleBar(); drawTitleBar();
if ( ! FWidget::getFocusWidget() )
{
if ( focus_widget && focus_widget->isVisible() && focus_widget->isShown() ) if ( focus_widget && focus_widget->isVisible() && focus_widget->isShown() )
{ {
focus_widget->setFocus(); focus_widget->setFocus();
@ -603,7 +738,6 @@ void FDialog::onWindowActive (FEvent*)
else else
focusFirstChild(); focusFirstChild();
} }
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FDialog::onWindowInactive (FEvent*) void FDialog::onWindowInactive (FEvent*)

View File

@ -28,6 +28,8 @@
#ifndef _FDIALOG_H #ifndef _FDIALOG_H
#define _FDIALOG_H #define _FDIALOG_H
#include "fmenu.h"
#include "fmenuitem.h"
#include "fwindow.h" #include "fwindow.h"
@ -54,6 +56,8 @@ class FDialog : public FWindow
FPoint TitleBarClickPos; FPoint TitleBarClickPos;
FRect oldGeometry; // required by move() FRect oldGeometry; // required by move()
FWidget* focus_widget; FWidget* focus_widget;
FMenu* dialog_menu;
FMenuItem* dgl_menuitem;
private: private:
FDialog (const FDialog&); FDialog (const FDialog&);
@ -61,6 +65,7 @@ class FDialog : public FWindow
void init(); void init();
void drawBorder(); void drawBorder();
void drawTitleBar(); void drawTitleBar();
void cb_close (FWidget*, void*);
protected: protected:
virtual void done (int); virtual void done (int);

View File

@ -130,6 +130,7 @@ class FMenu : public FWindow, public FMenuList
private: private:
friend class FApplication; friend class FApplication;
friend class FCheckMenuItem; friend class FCheckMenuItem;
friend class FDialog;
friend class FMenuBar; friend class FMenuBar;
friend class FMenuItem; friend class FMenuItem;
friend class FRadioMenuItem; friend class FRadioMenuItem;

View File

@ -2,6 +2,7 @@
// Provides: class FMenuItem // Provides: class FMenuItem
#include "fapp.h" #include "fapp.h"
#include "fdialog.h"
#include "fmenu.h" #include "fmenu.h"
#include "fmenubar.h" #include "fmenubar.h"
#include "fmenulist.h" #include "fmenulist.h"
@ -246,6 +247,12 @@ void FMenuItem::processClicked()
// protected methods of FMenuItem // protected methods of FMenuItem
//----------------------------------------------------------------------
bool FMenuItem::isWindowsMenu (FWidget* w) const
{
return w->isDialog();
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
bool FMenuItem::isMenuBar (FWidget* w) const bool FMenuItem::isMenuBar (FWidget* w) const
{ {
@ -369,6 +376,52 @@ void FMenuItem::onKeyPress (FKeyEvent* ev)
} }
} }
//----------------------------------------------------------------------
void FMenuItem::onMouseDoubleClick (FMouseEvent* ev)
{
if ( super_menu )
{
const FPoint& g = ev->getGlobalPos();
int b = ev->getButton();
if ( isMenu(super_menu) )
{
FMenu* smenu = dynamic_cast<FMenu*>(super_menu);
if ( smenu )
{
const FPoint& p2 = smenu->globalToLocalPos(g);
FMouseEvent* _ev = new FMouseEvent (fc::MouseDoubleClick_Event, p2, g, b);
smenu->onMouseDoubleClick(_ev);
delete _ev;
}
}
if ( isMenuBar(super_menu) )
{
FMenuBar* mbar = dynamic_cast<FMenuBar*>(super_menu);
if ( mbar )
{
const FPoint& p2 = mbar->globalToLocalPos(g);
FMouseEvent* _ev = new FMouseEvent (fc::MouseDoubleClick_Event, p2, g, b);
mbar->onMouseDoubleClick(_ev);
delete _ev;
}
}
if ( isWindowsMenu(super_menu) )
{
FDialog* dgl = dynamic_cast<FDialog*>(super_menu);
if ( dgl )
{
const FPoint& p2 = dgl->globalToLocalPos(g);
FMouseEvent* _ev = new FMouseEvent (fc::MouseDoubleClick_Event, p2, g, b);
dgl->onMouseDoubleClick(_ev);
delete _ev;
}
}
}
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
void FMenuItem::onMouseDown (FMouseEvent* ev) void FMenuItem::onMouseDown (FMouseEvent* ev)
{ {
@ -400,6 +453,18 @@ void FMenuItem::onMouseDown (FMouseEvent* ev)
delete _ev; delete _ev;
} }
} }
if ( isWindowsMenu(super_menu) )
{
FDialog* dgl = dynamic_cast<FDialog*>(super_menu);
if ( dgl )
{
const FPoint& p2 = dgl->globalToLocalPos(g);
FMouseEvent* _ev = new FMouseEvent (fc::MouseDown_Event, p2, g, b);
dgl->onMouseDown(_ev);
delete _ev;
}
}
} }
} }
@ -434,6 +499,18 @@ void FMenuItem::onMouseUp (FMouseEvent* ev)
delete _ev; delete _ev;
} }
} }
if ( isWindowsMenu(super_menu) )
{
FDialog* dgl = dynamic_cast<FDialog*>(super_menu);
if ( dgl )
{
const FPoint& p2 = dgl->globalToLocalPos(g);
FMouseEvent* _ev = new FMouseEvent (fc::MouseUp_Event, p2, g, b);
dgl->onMouseUp(_ev);
delete _ev;
}
}
} }
} }
@ -469,6 +546,17 @@ void FMenuItem::onMouseMove (FMouseEvent* ev)
} }
} }
if ( isWindowsMenu(super_menu) )
{
FDialog* dgl = dynamic_cast<FDialog*>(super_menu);
if ( dgl )
{
const FPoint& p2 = dgl->globalToLocalPos(g);
FMouseEvent* _ev = new FMouseEvent (fc::MouseMove_Event, p2, g, b);
dgl->onMouseMove(_ev);
delete _ev;
}
}
} }
} }

View File

@ -65,6 +65,7 @@ class FMenuItem : public FWidget
virtual void processClicked(); virtual void processClicked();
protected: protected:
bool isWindowsMenu (FWidget*) const;
bool isMenuBar (FWidget*) const; bool isMenuBar (FWidget*) const;
bool isMenu (FWidget*) const; bool isMenu (FWidget*) const;
FWidget* getSuperMenu() const; FWidget* getSuperMenu() const;
@ -88,6 +89,7 @@ class FMenuItem : public FWidget
using FWidget::delAccelerator; using FWidget::delAccelerator;
void delAccelerator (FWidget*); void delAccelerator (FWidget*);
void onKeyPress (FKeyEvent*); void onKeyPress (FKeyEvent*);
void onMouseDoubleClick (FMouseEvent*);
void onMouseDown (FMouseEvent*); void onMouseDown (FMouseEvent*);
void onMouseUp (FMouseEvent*); void onMouseUp (FMouseEvent*);
void onMouseMove (FMouseEvent*); void onMouseMove (FMouseEvent*);

View File

@ -54,6 +54,7 @@ FWidget::FWidget (FWidget* parent)
, adjustWidgetSizeGlobalShadow() , adjustWidgetSizeGlobalShadow()
, ignore_padding(false) , ignore_padding(false)
, window_object(false) , window_object(false)
, dialog_object(false)
, menu_object(false) , menu_object(false)
, flags(0) , flags(0)
, foregroundColor() , foregroundColor()

View File

@ -246,6 +246,7 @@ class FWidget : public FObject, public FTerm
FRect adjustWidgetSizeGlobalShadow; FRect adjustWidgetSizeGlobalShadow;
bool ignore_padding; bool ignore_padding;
bool window_object; bool window_object;
bool dialog_object;
bool menu_object; bool menu_object;
int flags; int flags;
short foregroundColor; short foregroundColor;
@ -331,6 +332,7 @@ class FWidget : public FObject, public FTerm
FWidget* parentWidget() const; FWidget* parentWidget() const;
bool isRootWidget() const; bool isRootWidget() const;
bool isWindow() const; bool isWindow() const;
bool isDialog() const;
bool isMenu() const; bool isMenu() const;
virtual bool close(); virtual bool close();
@ -580,6 +582,10 @@ inline bool FWidget::isShown() const
inline bool FWidget::isWindow() const inline bool FWidget::isWindow() const
{ return window_object; } { return window_object; }
//----------------------------------------------------------------------
inline bool FWidget::isDialog() const
{ return dialog_object; }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
inline bool FWidget::isMenu() const inline bool FWidget::isMenu() const
{ return menu_object; } { return menu_object; }