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>
* Use nl_langinfo to determine the numeric thousands separator
for Fstring::setFormatedNumber as default parameter

View File

@ -20,8 +20,6 @@ Missing Features
└──► 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
the window size on a resizeable dialog
- 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 )
{
FMenu* menu = static_cast<FMenu*>(open_menu);
@ -980,8 +980,6 @@ void FApplication::processMouseEvent()
menu->hide();
menu->hideSubMenus();
menu->hideSuperMenus();
if ( statusBar() )
statusBar()->clearMessage();
// No widget was been clicked
if ( ! clicked_widget )
@ -1375,7 +1373,9 @@ bool FApplication::sendEvent(FObject* receiver, FEvent* event)
window = FWindow::getWindowWidget(widget);
// 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() )
{

View File

@ -20,6 +20,8 @@ FDialog::FDialog(FWidget* parent)
, TitleBarClickPos()
, oldGeometry()
, focus_widget(0)
, dialog_menu()
, dgl_menuitem()
{
init();
}
@ -33,6 +35,8 @@ FDialog::FDialog (const FString& txt, FWidget* parent)
, TitleBarClickPos()
, oldGeometry()
, focus_widget(0)
, dialog_menu()
, dgl_menuitem()
{
init();
}
@ -88,12 +92,13 @@ FDialog::~FDialog() // destructor
//----------------------------------------------------------------------
void FDialog::init()
{
FWidget* rootObj = getRootWidget();
xmin = 1 + rootObj->getLeftPadding();
ymin = 1 + rootObj->getTopPadding();
xmax = rootObj->getWidth();
ymax = rootObj->getHeight();
width = 10;
height = 10;
xmin = 1;
ymin = 1;
xmax = width;
ymax = height;
client_xmin = 1;
client_ymin = 1;
client_xmax = width;
@ -106,6 +111,7 @@ void FDialog::init()
setGeometry (1, 1, 10, 10, false); // initialize geometry values
ignore_padding = true;
window_object = true;
dialog_object = true;
addWindow(this);
setActiveWindow(this);
@ -124,6 +130,25 @@ void FDialog::init()
old_focus->redraw();
}
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);
}
else if ( isMonochron() )
print ("[-]");
{
print ('[');
if ( dgl_menuitem )
print (dgl_menuitem->getText());
else
print ('-');
print (']');
}
else
print (" - ");
{
print (' ');
if ( dgl_menuitem )
print (dgl_menuitem->getText());
else
print ('-');
print (' ');
}
// fill with spaces (left of the title)
if ( getMaxColor() < 16 )
setBold();
if ( isActiveWindow() )
if ( isActiveWindow() || dialog_menu->isVisible() )
setColor (wc.titlebar_active_fg, wc.titlebar_active_bg);
else
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
//----------------------------------------------------------------------
void FDialog::done(int result)
@ -475,6 +525,47 @@ void FDialog::onMouseDown (FMouseEvent* ev)
}
if ( has_raised )
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 )
@ -537,6 +628,9 @@ void FDialog::onMouseUp (FMouseEvent* ev)
if ( ev->getButton() == fc::LeftButton )
{
int mouse_x = ev->getX();
int mouse_y = ev->getY();
if ( ! TitleBarClickPos.isNull()
&& titlebar_x > xpos+xmin+2
&& titlebar_x < xpos+xmin+width
@ -547,6 +641,24 @@ void FDialog::onMouseUp (FMouseEvent* ev)
move (currentPos + deltaPos);
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);
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,8 +711,14 @@ void FDialog::onMouseDoubleClick (FMouseEvent* ev)
FPoint gPos = ev->getGlobalPos();
if ( title_button.contains(gPos) )
{
dialog_menu->unselectItem();
dialog_menu->hide();
setClickedWidget(0);
close();
if ( isModal() )
done(FDialog::Reject);
else
close();
}
}
@ -591,18 +728,15 @@ void FDialog::onWindowActive (FEvent*)
if ( isVisible() && isShown() )
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->redraw();
if ( statusBar() )
statusBar()->drawMessage();
}
else
focusFirstChild();
focus_widget->setFocus();
focus_widget->redraw();
if ( statusBar() )
statusBar()->drawMessage();
}
else
focusFirstChild();
}
//----------------------------------------------------------------------

View File

@ -28,6 +28,8 @@
#ifndef _FDIALOG_H
#define _FDIALOG_H
#include "fmenu.h"
#include "fmenuitem.h"
#include "fwindow.h"
@ -48,12 +50,14 @@ class FDialog : public FWindow
};
private:
FString tb_text; // title bar text
int result_code;
bool maximized;
FPoint TitleBarClickPos;
FRect oldGeometry; // required by move()
FWidget* focus_widget;
FString tb_text; // title bar text
int result_code;
bool maximized;
FPoint TitleBarClickPos;
FRect oldGeometry; // required by move()
FWidget* focus_widget;
FMenu* dialog_menu;
FMenuItem* dgl_menuitem;
private:
FDialog (const FDialog&);
@ -61,6 +65,7 @@ class FDialog : public FWindow
void init();
void drawBorder();
void drawTitleBar();
void cb_close (FWidget*, void*);
protected:
virtual void done (int);

View File

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

View File

@ -2,6 +2,7 @@
// Provides: class FMenuItem
#include "fapp.h"
#include "fdialog.h"
#include "fmenu.h"
#include "fmenubar.h"
#include "fmenulist.h"
@ -246,6 +247,12 @@ void FMenuItem::processClicked()
// protected methods of FMenuItem
//----------------------------------------------------------------------
bool FMenuItem::isWindowsMenu (FWidget* w) const
{
return w->isDialog();
}
//----------------------------------------------------------------------
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)
{
@ -400,6 +453,18 @@ void FMenuItem::onMouseDown (FMouseEvent* 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;
}
}
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();
protected:
bool isWindowsMenu (FWidget*) const;
bool isMenuBar (FWidget*) const;
bool isMenu (FWidget*) const;
FWidget* getSuperMenu() const;
@ -88,6 +89,7 @@ class FMenuItem : public FWidget
using FWidget::delAccelerator;
void delAccelerator (FWidget*);
void onKeyPress (FKeyEvent*);
void onMouseDoubleClick (FMouseEvent*);
void onMouseDown (FMouseEvent*);
void onMouseUp (FMouseEvent*);
void onMouseMove (FMouseEvent*);

View File

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

View File

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