finalcut/src/fwidget.cpp

2524 lines
58 KiB
C++
Raw Normal View History

2017-11-04 07:03:53 +01:00
/***********************************************************************
* fwidget.cpp - Intermediate base class for all widget objects *
* *
* This file is part of the Final Cut widget toolkit *
* *
* Copyright 2015-2018 Markus Gans *
2017-11-04 07:03:53 +01:00
* *
* The Final Cut is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public License *
* as published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* The Final Cut is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* <http://www.gnu.org/licenses/>. *
***********************************************************************/
2015-05-23 13:35:12 +02:00
2017-09-11 03:06:02 +02:00
#include <vector>
#include "final/fapplication.h"
#include "final/fmenubar.h"
#include "final/fstatusbar.h"
#include "final/fwidget.h"
2015-05-23 13:35:12 +02:00
// global FWidget object
static FWidget* rootObject = 0;
// static class attributes
uInt FWidget::modal_dialogs;
FStatusBar* FWidget::statusbar = 0;
2015-08-09 23:44:11 +02:00
FMenuBar* FWidget::menubar = 0;
2015-05-23 13:35:12 +02:00
FWidget* FWidget::show_root_widget = 0;
FWidget* FWidget::redraw_root_widget = 0;
FWidget::widgetList* FWidget::window_list = 0;
FWidget::widgetList* FWidget::dialog_list = 0;
FWidget::widgetList* FWidget::always_on_top_list = 0;
2015-05-23 13:35:12 +02:00
FWidget::widgetList* FWidget::close_widget = 0;
FWidgetColors FWidget::wc;
2016-11-27 19:16:52 +01:00
bool FWidget::init_desktop;
bool FWidget::hideable;
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
// class FWidget
//----------------------------------------------------------------------
// constructors and destructor
//----------------------------------------------------------------------
2017-03-26 20:40:04 +02:00
FWidget::FWidget (FWidget* parent, bool disable_alt_screen)
: FVTerm(bool(! parent), disable_alt_screen)
, FObject(parent)
, accelerator_list(0)
2015-09-22 04:18:20 +02:00
, flags(0)
, callback_objects()
, member_callback_objects()
2015-09-22 04:18:20 +02:00
, enable(true)
, visible(true)
, shown(false)
, focus(false)
, focusable(true)
, visible_cursor(true)
2017-09-11 03:06:02 +02:00
, widget_cursor_position(-1, -1)
, size_hints()
, double_flatline_mask()
, padding()
, ignore_padding(false)
2017-09-11 03:06:02 +02:00
, wsize(1, 1, 1, 1)
, adjust_wsize(1, 1, 1, 1)
, adjust_wsize_term()
, adjust_wsize_shadow()
, adjust_wsize_term_shadow()
, offset()
, client_offset()
2017-09-11 03:06:02 +02:00
, wshadow(0, 0)
2016-10-09 02:06:06 +02:00
, foreground_color(fc::Default)
, background_color(fc::Default)
, statusbar_message()
2015-09-22 04:18:20 +02:00
{
if ( isEnabled() )
flags |= fc::active;
2017-06-11 17:47:50 +02:00
widget_object = true;
if ( ! parent )
2015-05-23 13:35:12 +02:00
{
assert ( ! rootObject
2017-11-26 22:37:18 +01:00
&& "FTerm: There should be only one root object" );
2015-05-23 13:35:12 +02:00
rootObject = this;
show_root_widget = 0;
redraw_root_widget = 0;
modal_dialogs = 0;
statusbar = 0;
init();
}
else
{
visible_cursor = ! hideable;
offset = parent->client_offset;
double_flatline_mask.top.resize (uLong(getWidth()), false);
double_flatline_mask.right.resize (uLong(getHeight()), false);
double_flatline_mask.bottom.resize (uLong(getWidth()), false);
double_flatline_mask.left.resize (uLong(getHeight()), false);
2015-05-23 13:35:12 +02:00
}
}
//----------------------------------------------------------------------
FWidget::~FWidget() // destructor
{
processDestroy();
delCallbacks();
2015-05-23 13:35:12 +02:00
FApplication::removeQueuedEvent(this);
2016-07-31 20:25:25 +02:00
// unset clicked widget
2015-05-23 13:35:12 +02:00
if ( this == getClickedWidget() )
setClickedWidget(0);
2016-07-31 20:25:25 +02:00
// unset the local window widget focus
if ( focus )
{
if ( FWindow* window = FWindow::getWindowWidget(this) )
2016-07-31 20:25:25 +02:00
window->setWindowFocusWidget(0);
}
// unset the global widget focus
2015-05-23 13:35:12 +02:00
if ( this == FWidget::getFocusWidget() )
FWidget::setFocusWidget(0);
2016-07-31 20:25:25 +02:00
// unset main widget
2015-05-23 13:35:12 +02:00
if ( this == getMainWidget() )
{
setMainWidget(0);
quit();
}
2016-07-31 20:25:25 +02:00
// finish the program
2015-05-23 13:35:12 +02:00
if ( rootObject == this )
finish();
2015-05-23 13:35:12 +02:00
}
// public methods of FWidget
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
FWidget* FWidget::getRootWidget() const
2015-05-23 13:35:12 +02:00
{
FWidget* obj = const_cast<FWidget*>(this);
FWidget* p_obj = getParentWidget();
while ( ! obj->isRootWidget() && p_obj )
{
obj = p_obj;
p_obj = p_obj->getParentWidget();
}
return obj;
}
2017-06-11 17:47:50 +02:00
//----------------------------------------------------------------------
2017-06-14 01:06:48 +02:00
FWidget* FWidget::getParentWidget() const
2017-06-11 17:47:50 +02:00
{
FObject* p_obj = getParent();
if ( p_obj && p_obj->isWidget() )
return static_cast<FWidget*>(p_obj);
else
return 0;
}
//----------------------------------------------------------------------
FWidget* FWidget::getMainWidget()
{
FWidget* main_widget = static_cast<FWidget*>(FApplication::main_widget);
return main_widget;
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
FWidget* FWidget::getFocusWidget() const
{
FWidget* focus_widget = static_cast<FWidget*>(FApplication::focus_widget);
return focus_widget;
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
FWidget* FWidget::getFirstFocusableWidget (FObjectList list)
{
if ( list.empty() )
return 0;
constFObjectIterator iter, last;
iter = list.begin();
last = list.end();
while ( iter != last )
{
2017-06-11 17:47:50 +02:00
if ( (*iter)->isWidget() )
{
FWidget* child = static_cast<FWidget*>(*iter);
2017-06-11 17:47:50 +02:00
if ( child->isEnabled() && child->acceptFocus() )
return child;
}
++iter;
}
return 0;
}
//----------------------------------------------------------------------
FWidget* FWidget::getLastFocusableWidget (FObjectList list)
{
if ( list.empty() )
return 0;
constFObjectIterator iter, first;
first = list.begin();
iter = list.end();
do
{
--iter;
2017-06-11 17:47:50 +02:00
if ( ! (*iter)->isWidget() )
continue;
FWidget* child = static_cast<FWidget*>(*iter);
if ( child->isEnabled() && child->acceptFocus() )
return child;
}
while ( iter != first );
return 0;
}
//----------------------------------------------------------------------
FWidget* FWidget::getClickedWidget()
{
FWidget* clicked_widget = static_cast<FWidget*>(FApplication::clicked_widget);
return clicked_widget;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
FWidget* FWidget::getMoveSizeWidget()
2015-05-23 13:35:12 +02:00
{
return FApplication::move_size_widget;
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
FWidget* FWidget::getOpenMenu()
{
FWidget* open_menu = static_cast<FWidget*>(FApplication::open_menu);
return open_menu;
}
//----------------------------------------------------------------------
FMenuBar* FWidget::getMenuBar()
{
if ( menubar )
return menubar;
else
return 0;
}
//----------------------------------------------------------------------
FStatusBar* FWidget::getStatusBar()
{
if ( statusbar )
return statusbar;
else
return 0;
}
//----------------------------------------------------------------------
FPoint FWidget::getPrintPos()
{
const FPoint cur = getPrintCursor();
int cx = cur.getX();
int cy = cur.getY();
return FPoint ( cx - offset.getX1() - getX() + 1
, cy - offset.getY1() - getY() + 1 );
}
//----------------------------------------------------------------------
std::vector<bool>& FWidget::doubleFlatLine_ref (fc::sides side)
{
assert ( side == fc::top
2017-11-26 22:37:18 +01:00
|| side == fc::right
|| side == fc::bottom
|| side == fc::left );
switch ( side )
{
case fc::top:
return double_flatline_mask.top;
case fc::right:
return double_flatline_mask.right;
case fc::bottom:
return double_flatline_mask.bottom;
case fc::left:
return double_flatline_mask.left;
}
return double_flatline_mask.left;
}
//----------------------------------------------------------------------
void FWidget::setMainWidget (FWidget* obj)
{
FApplication* fapp = static_cast<FApplication*>(rootObject);
fapp->setMainWidget(obj);
}
//----------------------------------------------------------------------
void FWidget::setFocusWidget (FWidget* obj)
{
FApplication::focus_widget = obj;
}
//----------------------------------------------------------------------
void FWidget::setClickedWidget (FWidget* obj)
{
FApplication::clicked_widget = obj;
}
//----------------------------------------------------------------------
void FWidget::setMoveSizeWidget (FWidget* obj)
{
FApplication::move_size_widget = obj;
}
//----------------------------------------------------------------------
void FWidget::setOpenMenu (FWidget* obj)
{
FApplication::open_menu = obj;
}
//----------------------------------------------------------------------
2017-03-26 20:40:04 +02:00
void FWidget::setStatusbarMessage (const FString& msg)
{
statusbar_message = msg;
}
//----------------------------------------------------------------------
bool FWidget::setEnable (bool on)
2017-06-11 17:47:50 +02:00
{
if ( on )
flags |= fc::active;
else
flags &= ~fc::active;
return enable = ( on ) ? true : false;
}
//----------------------------------------------------------------------
bool FWidget::setFocus (bool on)
{
FWindow* window;
FWidget* last_focus;
if ( ! enable )
return false;
if ( on )
flags |= fc::focus;
else
flags &= ~fc::focus;
if ( on == focus )
return true;
last_focus = FWidget::getFocusWidget();
// set widget focus
if ( on && ! focus )
{
int focusable_children = numOfFocusableChildren();
if ( last_focus )
last_focus->unsetFocus();
if ( (!isDialogWidget() && focusable_children == 0)
2017-11-26 22:37:18 +01:00
|| (isDialogWidget() && focusable_children == 1) )
{
FWidget::setFocusWidget(this);
}
}
window = FWindow::getWindowWidget(this);
// set window focus
if ( on && window )
2015-05-23 13:35:12 +02:00
{
if ( ! window->isWindowActive() )
{
bool has_raised = window->raiseWindow();
FWindow::setActiveWindow(window);
if ( has_raised && window->isVisible() && window->isShown() )
window->redraw();
}
window->setWindowFocusWidget(this);
2015-05-23 13:35:12 +02:00
}
return focus = ( on ) ? true : false;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::setColor ()
{
// Changes colors to the widget default colors
setColor (foreground_color, background_color);
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::setX (int x, bool adjust)
2015-05-23 13:35:12 +02:00
{
if ( getX() == x && wsize.getX() == x )
return;
2015-05-23 13:35:12 +02:00
if ( ! isWindowWidget() && x < 1 )
x = 1;
2015-05-23 13:35:12 +02:00
wsize.setX(x);
adjust_wsize.setX(x);
2015-05-23 13:35:12 +02:00
if ( adjust )
adjustSize();
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::setY (int y, bool adjust)
2015-05-23 13:35:12 +02:00
{
if ( getY() == y && wsize.getY() == y )
return;
if ( ! isWindowWidget() && y < 1 )
y = 1;
wsize.setY(y);
adjust_wsize.setY(y);
if ( adjust )
adjustSize();
}
//----------------------------------------------------------------------
void FWidget::setPos (int x, int y, bool adjust)
{
if ( getX() == x && wsize.getX() == x
2017-11-26 22:37:18 +01:00
&& getY() == y && wsize.getY() == y )
{
return;
2015-05-23 13:35:12 +02:00
}
if ( ! isWindowWidget() )
2015-05-23 13:35:12 +02:00
{
if ( x < 1 )
x = 1;
if ( y < 1 )
y = 1;
}
2015-05-23 13:35:12 +02:00
2017-09-11 03:06:02 +02:00
wsize.setPos(x, y);
adjust_wsize.setPos(x, y);
if ( adjust )
adjustSize();
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::setWidth (int width, bool adjust)
{
width = std::min (width, size_hints.max_width);
width = std::max (width, size_hints.min_width);
if ( getWidth() == width && wsize.getWidth() == width )
return;
if ( width < 1 )
width = 1;
wsize.setWidth(width);
adjust_wsize.setWidth(width);
2015-05-23 13:35:12 +02:00
if ( adjust )
adjustSize();
2015-05-23 13:35:12 +02:00
double_flatline_mask.top.resize (uLong(getWidth()), false);
double_flatline_mask.bottom.resize (uLong(getWidth()), false);
}
//----------------------------------------------------------------------
void FWidget::setHeight (int height, bool adjust)
{
height = std::min (height, size_hints.max_height);
height = std::max (height, size_hints.min_height);
2015-05-23 13:35:12 +02:00
if ( getHeight() == height && wsize.getHeight() == height )
return;
2015-05-23 13:35:12 +02:00
if ( height < 1 )
height = 1;
2015-05-23 13:35:12 +02:00
wsize.setHeight(height);
adjust_wsize.setHeight(height);
if ( adjust )
adjustSize();
double_flatline_mask.right.resize (uLong(getHeight()), false);
double_flatline_mask.left.resize (uLong(getHeight()), false);
2015-05-23 13:35:12 +02:00
}
2016-05-16 21:11:32 +02:00
//----------------------------------------------------------------------
void FWidget::setSize (int width, int height, bool adjust)
2016-05-16 21:11:32 +02:00
{
width = std::min (width, size_hints.max_width);
width = std::max (width, size_hints.min_width);
height = std::min (height, size_hints.max_height);
height = std::max (height, size_hints.min_height);
if ( getWidth() == width && wsize.getWidth() == width
2017-11-26 22:37:18 +01:00
&& getHeight() == height && wsize.getHeight() == height )
2016-05-16 21:11:32 +02:00
return;
if ( width < 1 )
width = 1;
2016-05-16 21:11:32 +02:00
if ( height < 1 )
height = 1;
wsize.setWidth(width);
wsize.setHeight(height);
adjust_wsize.setWidth(width);
adjust_wsize.setHeight(height);
if ( adjust )
adjustSize();
double_flatline_mask.top.resize (uLong(getWidth()), false);
double_flatline_mask.right.resize (uLong(getHeight()), false);
double_flatline_mask.bottom.resize (uLong(getWidth()), false);
double_flatline_mask.left.resize (uLong(getHeight()), false);
}
//----------------------------------------------------------------------
void FWidget::setTopPadding (int top, bool adjust)
{
if ( padding.top == top )
return;
2017-01-22 23:04:40 +01:00
padding.top = top;
if ( adjust )
{
if ( isRootWidget() )
2016-05-16 21:11:32 +02:00
{
FWidget* r = rootObject;
r->client_offset.setY1 (r->padding.top);
adjustSizeGlobal();
2016-05-16 21:11:32 +02:00
}
else
adjustSize();
2016-05-16 21:11:32 +02:00
}
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::setLeftPadding (int left, bool adjust)
2015-05-23 13:35:12 +02:00
{
if ( padding.left == left )
2015-05-23 13:35:12 +02:00
return;
2017-01-22 23:04:40 +01:00
padding.left = left;
2015-05-23 13:35:12 +02:00
if ( adjust )
{
if ( isRootWidget() )
{
FWidget* r = rootObject;
r->client_offset.setX1 (r->padding.left);
adjustSizeGlobal();
}
else
adjustSize();
}
2015-05-23 13:35:12 +02:00
}
2015-08-09 23:44:11 +02:00
//----------------------------------------------------------------------
void FWidget::setBottomPadding (int bottom, bool adjust)
2015-08-09 23:44:11 +02:00
{
if ( padding.bottom == bottom )
2015-08-09 23:44:11 +02:00
return;
2017-01-22 23:04:40 +01:00
padding.bottom = bottom;
2015-08-09 23:44:11 +02:00
if ( adjust )
{
if ( isRootWidget() )
{
FWidget* r = rootObject;
r->client_offset.setY2 (r->getHeight() - 1 - r->padding.bottom);
adjustSizeGlobal();
}
else
adjustSize();
}
2015-08-09 23:44:11 +02:00
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::setRightPadding (int right, bool adjust)
2015-05-23 13:35:12 +02:00
{
if ( padding.right == right )
return;
2017-01-22 23:04:40 +01:00
padding.right = right;
if ( adjust )
{
if ( isRootWidget() )
{
FWidget* r = rootObject;
r->client_offset.setX2 (r->getWidth() - 1 - r->padding.right);
adjustSizeGlobal();
}
else
adjustSize();
}
}
//----------------------------------------------------------------------
void FWidget::setParentOffset()
{
FWidget* p = getParentWidget();
if ( p )
offset = p->client_offset;
}
//----------------------------------------------------------------------
void FWidget::setTermOffset()
{
FWidget* r = getRootWidget();
int w = r->getWidth();
int h = r->getHeight();
offset.setCoordinates (0, 0, w - 1, h - 1);
}
//----------------------------------------------------------------------
void FWidget::setTermOffsetWithPadding()
{
FWidget* r = getRootWidget();
offset.setCoordinates ( r->getLeftPadding()
, r->getTopPadding()
, r->getWidth() - 1 - r->getRightPadding()
, r->getHeight() - 1 - r->getBottomPadding() );
}
//----------------------------------------------------------------------
void FWidget::setTermSize (int w, int h)
{
// Set xterm size to w x h
if ( isXTerminal() )
{
rootObject->wsize.setRect(1, 1, w, h);
rootObject->adjust_wsize = rootObject->wsize;
FTerm::setTermSize (w, h); // w = columns / h = lines
detectTermSize();
}
}
//----------------------------------------------------------------------
void FWidget::setGeometry (int x, int y, int w, int h, bool adjust)
{
// Sets the geometry of the widget relative to its parent
int term_x
, term_y;
2015-05-23 13:35:12 +02:00
w = std::min (w, size_hints.max_width);
w = std::max (w, size_hints.min_width);
h = std::min (h, size_hints.max_height);
h = std::max (h, size_hints.min_height);
2015-05-23 13:35:12 +02:00
if ( getX() == x && getY() == y && getWidth() == w && getHeight() == h )
return;
if ( ! isWindowWidget() )
{
( x < 1 ) ? wsize.setX(1) : wsize.setX(x);
( y < 1 ) ? wsize.setY(1) : wsize.setY(y);
}
else
{
wsize.setX(x);
wsize.setY(y);
}
( w < 1 ) ? wsize.setWidth(1) : wsize.setWidth(w);
( h < 1 ) ? wsize.setHeight(1) : wsize.setHeight(h);
adjust_wsize = wsize;
term_x = getTermX();
term_y = getTermY();
2015-05-23 13:35:12 +02:00
client_offset.setCoordinates ( term_x - 1 + padding.left
, term_y - 1 + padding.top
, term_x - 2 + getWidth() - padding.right
, term_y - 2 + getHeight() - padding.bottom );
2015-05-23 13:35:12 +02:00
double_flatline_mask.top.resize (uLong(getWidth()), false);
double_flatline_mask.right.resize (uLong(getHeight()), false);
double_flatline_mask.bottom.resize (uLong(getWidth()), false);
double_flatline_mask.left.resize (uLong(getHeight()), false);
2015-05-23 13:35:12 +02:00
if ( adjust )
adjustSize();
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
bool FWidget::setCursorPos (register int x, register int y)
{
// sets the input cursor position
2017-09-11 03:06:02 +02:00
widget_cursor_position.setPoint(x, y);
2015-05-23 13:35:12 +02:00
if ( (flags & fc::focus) == 0 || isWindowWidget() )
return false;
2015-05-23 13:35:12 +02:00
if ( ! FWindow::getWindowWidget(this) )
return false;
term_area* area = getPrintArea();
if ( area->widget )
{
int widget_offsetX = getTermX() - area->widget->getTermX();
int widget_offsetY = getTermY() - area->widget->getTermY();
if ( isChildPrintArea() )
{
widget_offsetX += (1 - area->widget->getLeftPadding());
widget_offsetY += (1 - area->widget->getTopPadding());
}
setAreaCursor ( widget_offsetX + x
, widget_offsetY + y
, visible_cursor
, area );
return true;
}
2015-05-23 13:35:12 +02:00
return false;
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::setPrintPos (register int x, register int y)
{
setPrintCursor ( offset.getX1() + getX() + x - 1,
offset.getY1() + getY() + y - 1 );
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::setDoubleFlatLine (fc::sides side, bool bit)
{
uLong length;
2015-05-23 13:35:12 +02:00
assert ( side == fc::top
2017-11-26 22:37:18 +01:00
|| side == fc::right
|| side == fc::bottom
|| side == fc::left );
2015-05-23 13:35:12 +02:00
switch ( side )
{
case fc::top:
length = double_flatline_mask.top.size();
double_flatline_mask.top.assign(length, bit);
2015-05-23 13:35:12 +02:00
break;
case fc::right:
length = double_flatline_mask.right.size();
double_flatline_mask.right.assign(length, bit);
2015-05-23 13:35:12 +02:00
break;
case fc::bottom:
length = double_flatline_mask.bottom.size();
double_flatline_mask.bottom.assign(length, bit);
2015-05-23 13:35:12 +02:00
break;
case fc::left:
length = double_flatline_mask.left.size();
double_flatline_mask.left.assign(length, bit);
break;
2015-05-23 13:35:12 +02:00
}
}
//----------------------------------------------------------------------
void FWidget::setDoubleFlatLine (fc::sides side, int pos, bool bit)
{
uLong length, index;
2015-05-23 13:35:12 +02:00
assert ( side == fc::top
2017-11-26 22:37:18 +01:00
|| side == fc::right
|| side == fc::bottom
|| side == fc::left );
2015-05-23 13:35:12 +02:00
assert ( pos >= 1 );
2015-05-23 13:35:12 +02:00
index = uLong(pos - 1);
2015-05-23 13:35:12 +02:00
switch ( side )
{
case fc::top:
length = double_flatline_mask.top.size();
2015-05-23 13:35:12 +02:00
if ( index < length )
double_flatline_mask.top[index] = bit;
2015-05-23 13:35:12 +02:00
break;
2015-05-23 13:35:12 +02:00
case fc::right:
length = double_flatline_mask.right.size();
2015-05-23 13:35:12 +02:00
if ( index < length )
double_flatline_mask.right[index] = bit;
2015-05-23 13:35:12 +02:00
break;
2015-05-23 13:35:12 +02:00
case fc::bottom:
length = double_flatline_mask.bottom.size();
2015-05-23 13:35:12 +02:00
if ( index < length )
double_flatline_mask.bottom[index] = bit;
2015-05-23 13:35:12 +02:00
break;
2015-05-23 13:35:12 +02:00
case fc::left:
length = double_flatline_mask.left.size();
2015-05-23 13:35:12 +02:00
if ( index < length )
double_flatline_mask.left[index] = bit;
break;
}
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
FWidget* FWidget::childWidgetAt (FWidget* p, int x, int y)
2015-05-23 13:35:12 +02:00
{
if ( p && p->hasChildren() )
2015-05-23 13:35:12 +02:00
{
constFObjectIterator iter, last;
iter = p->begin();
last = p->end();
while ( iter != last )
{
2017-06-11 17:47:50 +02:00
if ( ! (*iter)->isWidget() )
{
++iter;
continue;
}
FWidget* widget = static_cast<FWidget*>(*iter);
2015-05-23 13:35:12 +02:00
if ( widget->isEnabled()
2017-11-26 22:37:18 +01:00
&& widget->isVisible()
&& ! widget->isWindowWidget()
&& widget->getTermGeometry().contains(x, y) )
2015-05-23 13:35:12 +02:00
{
FWidget* child = childWidgetAt(widget, x, y);
return ( child != 0 ) ? child : widget;
2015-05-23 13:35:12 +02:00
}
++iter;
2015-05-23 13:35:12 +02:00
}
}
return 0;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
int FWidget::numOfFocusableChildren()
2015-05-23 13:35:12 +02:00
{
constFObjectIterator iter, last;
2015-05-23 13:35:12 +02:00
if ( ! hasChildren() )
2015-05-23 13:35:12 +02:00
return 0;
int num = 0;
iter = FObject::begin();
last = FObject::end();
2015-05-23 13:35:12 +02:00
while ( iter != last )
2015-05-23 13:35:12 +02:00
{
2017-06-11 17:47:50 +02:00
if ( (*iter)->isWidget() )
{
FWidget* widget = static_cast<FWidget*>(*iter);
2017-06-11 17:47:50 +02:00
if ( widget->acceptFocus() )
num++;
}
2015-05-23 13:35:12 +02:00
++iter;
}
2015-05-23 13:35:12 +02:00
return num;
}
//----------------------------------------------------------------------
bool FWidget::close()
{
2016-01-17 02:57:08 +01:00
FCloseEvent ev(fc::Close_Event);
2015-09-20 05:44:50 +02:00
FApplication::sendEvent(this, &ev);
2015-05-23 13:35:12 +02:00
2015-09-20 05:44:50 +02:00
if ( ev.isAccepted() )
2015-05-23 13:35:12 +02:00
{
if ( this == getMainWidget() )
quit();
else
{
hide();
2016-01-24 14:53:09 +01:00
if ( (flags & fc::modal) == 0 )
2015-05-23 13:35:12 +02:00
close_widget->push_back(this);
}
return true;
}
else
return false;
}
//----------------------------------------------------------------------
2017-03-26 20:40:04 +02:00
void FWidget::addCallback ( const FString& cb_signal
, FCallback cb_handler
2015-09-22 04:18:20 +02:00
, data_ptr data )
2015-05-23 13:35:12 +02:00
{
// add a (normal) function pointer as callback
callback_data obj = { cb_signal, cb_handler, data };
callback_objects.push_back(obj);
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
2017-03-26 20:40:04 +02:00
void FWidget::addCallback ( const FString& cb_signal
2015-09-22 04:18:20 +02:00
, FWidget* cb_instance
, FMemberCallback cb_handler
2015-09-22 04:18:20 +02:00
, data_ptr data )
2015-05-23 13:35:12 +02:00
{
// add a member function pointer as callback
member_callback_data obj = { cb_signal, cb_instance, cb_handler, data };
member_callback_objects.push_back(obj);
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::delCallback (FCallback cb_handler)
2015-05-23 13:35:12 +02:00
{
// delete a cb_handler function pointer
CallbackObjects::iterator iter;
if ( callback_objects.empty() )
2015-05-23 13:35:12 +02:00
return;
iter = callback_objects.begin();
2015-05-23 13:35:12 +02:00
while ( iter != callback_objects.end() )
2015-05-23 13:35:12 +02:00
{
if ( iter->cb_handler == cb_handler )
iter = callback_objects.erase(iter);
2015-05-23 13:35:12 +02:00
else
++iter;
}
}
//----------------------------------------------------------------------
void FWidget::delCallback (FWidget* cb_instance)
{
// delete all member function pointer from cb_instance
2015-05-23 13:35:12 +02:00
FWidget::MemberCallbackObjects::iterator iter;
if ( member_callback_objects.empty() )
2015-05-23 13:35:12 +02:00
return;
iter = member_callback_objects.begin();
2015-05-23 13:35:12 +02:00
while ( iter != member_callback_objects.end() )
2015-05-23 13:35:12 +02:00
{
if ( iter->cb_instance == cb_instance )
iter = member_callback_objects.erase(iter);
2015-05-23 13:35:12 +02:00
else
++iter;
}
}
//----------------------------------------------------------------------
void FWidget::delCallbacks()
{
// delete all callbacks from this widget
member_callback_objects.clear(); // member function pointer
callback_objects.clear(); // function pointer
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
2017-03-26 20:40:04 +02:00
void FWidget::emitCallback (const FString& emit_signal)
2015-05-23 13:35:12 +02:00
{
// member function pointer
if ( ! member_callback_objects.empty() )
2015-05-23 13:35:12 +02:00
{
MemberCallbackObjects::const_iterator m_iter, m_end;
m_iter = member_callback_objects.begin();
m_end = member_callback_objects.end();
2015-05-23 13:35:12 +02:00
while ( m_iter != m_end )
{
if ( m_iter->cb_signal == emit_signal )
{
FMemberCallback callback = m_iter->cb_handler;
// call the member function pointer
(m_iter->cb_instance->*callback)(this, m_iter->data);
}
2015-05-23 13:35:12 +02:00
++m_iter;
}
}
2015-05-23 13:35:12 +02:00
// function pointer
if ( ! callback_objects.empty() )
2015-05-23 13:35:12 +02:00
{
CallbackObjects::const_iterator iter, last;
iter = callback_objects.begin();
last = callback_objects.end();
2015-05-23 13:35:12 +02:00
while ( iter != last )
2015-05-23 13:35:12 +02:00
{
if ( iter->cb_signal == emit_signal )
{
FCallback callback = iter->cb_handler;
// call the function pointer
callback(this, iter->data);
}
2015-05-23 13:35:12 +02:00
++iter;
}
}
}
//----------------------------------------------------------------------
void FWidget::addAccelerator (int key, FWidget* obj)
{
FWidget* widget = FWindow::getWindowWidget(obj);
2015-05-23 13:35:12 +02:00
accelerator accel = { key, obj };
if ( ! widget || widget == statusbar || widget == menubar )
widget = getRootWidget();
if ( widget && widget->accelerator_list )
widget->accelerator_list->push_back(accel);
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::delAccelerator (FWidget* obj)
{
FWidget* widget = FWindow::getWindowWidget(this);
if ( ! widget || widget == statusbar || widget == menubar )
widget = getRootWidget();
if ( widget
2017-11-26 22:37:18 +01:00
&& widget->accelerator_list
&& ! widget->accelerator_list->empty() )
2015-05-23 13:35:12 +02:00
{
FWidget::Accelerators::iterator iter;
iter = widget->accelerator_list->begin();
2015-05-23 13:35:12 +02:00
while ( iter != widget->accelerator_list->end() )
2015-05-23 13:35:12 +02:00
{
if ( iter->object == obj )
iter = widget->accelerator_list->erase(iter);
2015-05-23 13:35:12 +02:00
else
++iter;
}
}
}
//----------------------------------------------------------------------
void FWidget::redraw()
{
if ( ! redraw_root_widget )
redraw_root_widget = this;
if ( isRootWidget() )
{
startTerminalUpdate();
// clean desktop
2015-05-23 13:35:12 +02:00
setColor (wc.term_fg, wc.term_bg);
clearArea (vdesktop);
2015-05-23 13:35:12 +02:00
}
else if ( ! visible )
return;
draw();
if ( isRootWidget() )
drawWindows();
2015-05-23 13:35:12 +02:00
else
drawChildren();
2015-05-23 13:35:12 +02:00
if ( isRootWidget() )
finishTerminalUpdate();
2015-05-23 13:35:12 +02:00
if ( redraw_root_widget == this )
{
updateTerminal();
flush_out();
redraw_root_widget = 0;
}
}
//----------------------------------------------------------------------
void FWidget::resize()
{
if ( isRootWidget() )
2015-05-23 13:35:12 +02:00
{
detectTermSize();
FRect term_geometry = getTermGeometry();
term_geometry.move (-1, -1);
2016-10-09 02:06:06 +02:00
resizeVTerm (term_geometry);
resizeArea (term_geometry, getShadow(), vdesktop);
2016-05-16 23:36:13 +02:00
adjustSizeGlobal();
2015-05-23 13:35:12 +02:00
}
else
adjustSize();
2015-10-11 21:56:16 +02:00
// resize the four double-flatline-masks
double_flatline_mask.top.resize (uLong(getWidth()), false);
double_flatline_mask.right.resize (uLong(getHeight()), false);
double_flatline_mask.bottom.resize (uLong(getWidth()), false);
double_flatline_mask.left.resize (uLong(getHeight()), false);
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::show()
{
if ( ! visible )
return;
2016-11-27 19:16:52 +01:00
if ( ! init_desktop )
{
2017-03-26 20:40:04 +02:00
#if defined(__linux__)
// Important: Do not use setNewFont() or setVGAFont() after
// the console character mapping has been initialized
initLinuxConsoleCharMap();
2017-03-26 20:40:04 +02:00
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__)
initFreeBSDConsoleCharMap();
#endif
// set xterm underline cursor
setXTermCursorStyle(fc::blinking_underline);
// set xterm color settings to defaults
setXTermDefaults();
// draw the vdesktop
FWidget* r = getRootWidget();
setColor(r->getForegroundColor(), r->getBackgroundColor());
clearArea (vdesktop);
2016-11-27 19:16:52 +01:00
init_desktop = true;
}
2015-05-23 13:35:12 +02:00
if ( ! show_root_widget )
{
startTerminalUpdate();
2015-05-23 13:35:12 +02:00
show_root_widget = this;
}
draw();
shown = true;
if ( hasChildren() )
2015-05-23 13:35:12 +02:00
{
constFObjectIterator iter, last;
iter = FObject::begin();
last = FObject::end();
2015-05-23 13:35:12 +02:00
while ( iter != last )
2015-05-23 13:35:12 +02:00
{
2017-06-11 17:47:50 +02:00
if ( (*iter)->isWidget() )
{
FWidget* widget = static_cast<FWidget*>(*iter);
widget->show();
}
2015-05-23 13:35:12 +02:00
++iter;
}
}
if ( show_root_widget && show_root_widget == this )
{
finishTerminalUpdate();
2015-05-23 13:35:12 +02:00
updateTerminal();
flush_out();
show_root_widget = 0;
}
2016-01-17 02:57:08 +01:00
FShowEvent show_ev (fc::Show_Event);
2015-09-20 05:44:50 +02:00
FApplication::sendEvent(this, &show_ev);
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::hide()
{
if ( visible )
{
visible = false;
shown = false;
if ( ! isDialogWidget()
2017-11-26 22:37:18 +01:00
&& FWidget::getFocusWidget() == this
&& ! focusPrevChild() )
2015-05-23 13:35:12 +02:00
{
if ( FWidget::getFocusWidget() )
FWidget::getFocusWidget()->unsetFocus();
FWidget::setFocusWidget(getParentWidget());
2015-05-23 13:35:12 +02:00
}
2016-01-17 02:57:08 +01:00
FHideEvent hide_ev (fc::Hide_Event);
2015-09-20 05:44:50 +02:00
FApplication::sendEvent(this, &hide_ev);
2015-05-23 13:35:12 +02:00
}
}
//----------------------------------------------------------------------
2016-05-22 19:18:16 +02:00
bool FWidget::focusFirstChild()
2015-05-23 13:35:12 +02:00
{
constFObjectIterator iter, last;
2015-05-23 13:35:12 +02:00
if ( ! hasChildren() )
2015-05-23 13:35:12 +02:00
return false;
iter = FObject::begin();
last = FObject::end();
2015-05-23 13:35:12 +02:00
while ( iter != last )
2015-05-23 13:35:12 +02:00
{
2017-06-11 17:47:50 +02:00
if ( ! (*iter)->isWidget() )
{
++iter;
continue;
}
2015-05-23 13:35:12 +02:00
FWidget* widget = static_cast<FWidget*>(*iter);
if ( widget->isEnabled()
2017-11-26 22:37:18 +01:00
&& widget->acceptFocus()
&& ! widget->isMenuWidget() )
2015-05-23 13:35:12 +02:00
{
widget->setFocus();
2015-05-23 13:35:12 +02:00
if ( widget->numOfChildren() >= 1 )
{
if ( ! widget->focusFirstChild() && widget->isWindowWidget() )
{
++iter;
continue;
}
}
2015-05-23 13:35:12 +02:00
return true;
}
2015-05-23 13:35:12 +02:00
++iter;
}
return false;
}
//----------------------------------------------------------------------
2016-05-22 19:18:16 +02:00
bool FWidget::focusLastChild()
2015-05-23 13:35:12 +02:00
{
constFObjectIterator iter, first;
2015-05-23 13:35:12 +02:00
if ( ! hasChildren() )
2015-05-23 13:35:12 +02:00
return false;
iter = FObject::end();
first = FObject::begin();
2015-05-23 13:35:12 +02:00
do
{
--iter;
2017-06-11 17:47:50 +02:00
if ( ! (*iter)->isWidget() )
continue;
2015-05-23 13:35:12 +02:00
FWidget* widget = static_cast<FWidget*>(*iter);
if ( widget->isEnabled()
2017-11-26 22:37:18 +01:00
&& widget->acceptFocus()
&& ! widget->isMenuWidget() )
2015-05-23 13:35:12 +02:00
{
widget->setFocus();
2015-05-23 13:35:12 +02:00
if ( widget->numOfChildren() >= 1 )
{
if ( ! widget->focusLastChild() && widget->isWindowWidget() )
continue;
}
2015-05-23 13:35:12 +02:00
return true;
}
}
while ( iter != first );
2015-05-23 13:35:12 +02:00
return false;
}
//----------------------------------------------------------------------
void FWidget::detectTermSize()
2015-05-23 13:35:12 +02:00
{
FWidget* r = rootObject;
FTerm::detectTermSize();
r->adjust_wsize.setRect (1, 1, getDesktopWidth(), getDesktopHeight());
r->offset.setRect (0, 0, getDesktopWidth(), getDesktopHeight());
r->client_offset.setCoordinates
(
r->padding.left,
r->padding.top,
getDesktopWidth() - 1 - r->padding.right,
getDesktopHeight() - 1 - r->padding.bottom
);
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::move (int dx, int dy)
{
2017-09-11 03:06:02 +02:00
wsize.move(dx, dy);
adjust_wsize.move(dx, dy);
}
//----------------------------------------------------------------------
void FWidget::drawShadow()
{
bool trans_shadow = ((flags & fc::trans_shadow) != 0);
2015-05-23 13:35:12 +02:00
if ( isMonochron() && ! trans_shadow )
return;
if ( (term_encoding == fc::VT100 && ! trans_shadow)
2017-11-26 22:37:18 +01:00
|| (term_encoding == fc::ASCII && ! trans_shadow) )
2015-05-23 13:35:12 +02:00
{
clearShadow();
return;
}
int x1 = 1
, x2 = getWidth()
, y1 = 1
, y2 = getHeight();
if ( trans_shadow )
{
// transparent shadow
drawTransparentShadow (x1, y1, x2, y2);
}
else
2015-05-23 13:35:12 +02:00
{
// non-transparent shadow
drawBlockShadow (x1, y1, x2, y2);
}
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::clearShadow()
2015-05-23 13:35:12 +02:00
{
if ( isMonochron() )
return;
2015-05-23 13:35:12 +02:00
2017-11-02 16:05:34 +01:00
int w = getWidth()
, h = getHeight();
2015-05-23 13:35:12 +02:00
if ( isWindowWidget() )
{
setColor (wc.shadow_fg, wc.shadow_bg);
setInheritBackground(); // current background color will be ignored
}
else if ( FWidget* p = getParentWidget() )
setColor (wc.shadow_fg, p->getBackgroundColor());
2015-05-23 13:35:12 +02:00
2017-11-02 16:05:34 +01:00
if ( w <= offset.getX2() )
2015-09-28 04:31:29 +02:00
{
2017-11-02 16:05:34 +01:00
for (int i = 1; i <= getHeight(); i++)
{
2017-11-02 16:05:34 +01:00
setPrintPos (w + 1, i);
print (' '); // clear █
}
2015-09-28 04:31:29 +02:00
}
2017-11-02 16:05:34 +01:00
if ( h <= offset.getY2() )
{
2017-11-02 16:05:34 +01:00
setPrintPos (2, h + 1);
for (int i = 1; i <= getWidth(); i++)
2017-09-11 03:06:02 +02:00
print (' '); // clear ▀
}
if ( isWindowWidget() )
unsetInheritBackground();
}
//----------------------------------------------------------------------
void FWidget::drawFlatBorder()
{
if ( ! isNewFont() )
return;
int x1 = 1
, x2 = getWidth() + 1
, y1 = 0
, y2 = getHeight() + 1;
if ( FWidget* p = getParentWidget() )
setColor (wc.dialog_fg, p->getBackgroundColor());
else
setColor (wc.dialog_fg, wc.dialog_bg);
for (int y = 0; y < getHeight(); y++)
{
setPrintPos (x1 - 1, y1 + y + 1);
if ( double_flatline_mask.left[uLong(y)] )
2017-09-11 03:06:02 +02:00
// left+right line (on left side)
print (fc::NF_rev_border_line_right_and_left);
else
2017-09-11 03:06:02 +02:00
// right line (on left side)
print (fc::NF_rev_border_line_right);
}
setPrintPos (x2, y1 + 1);
for (int y = 0; y < getHeight(); y++)
{
if ( double_flatline_mask.right[uLong(y)] )
2017-09-11 03:06:02 +02:00
// left+right line (on right side)
print (fc::NF_rev_border_line_right_and_left);
else
2017-09-11 03:06:02 +02:00
// left line (on right side)
print (fc::NF_border_line_left);
2015-05-23 13:35:12 +02:00
setPrintPos (x2, y1 + y + 2);
}
2015-05-23 13:35:12 +02:00
setPrintPos (x1, y1);
2015-05-23 13:35:12 +02:00
for (int x = 0; x < getWidth(); x++)
{
if ( double_flatline_mask.top[uLong(x)] )
2017-09-11 03:06:02 +02:00
// top+bottom line (at top)
print (fc::NF_border_line_up_and_down);
else
2017-09-11 03:06:02 +02:00
// bottom line (at top)
print (fc::NF_border_line_bottom);
}
setPrintPos (x1, y2);
for (int x = 0; x < getWidth(); x++)
{
if ( double_flatline_mask.bottom[uLong(x)] )
2017-09-11 03:06:02 +02:00
// top+bottom line (at bottom)
print (fc::NF_border_line_up_and_down);
else
2017-09-11 03:06:02 +02:00
// top line (at bottom)
print (fc::NF_border_line_upper);
}
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::clearFlatBorder()
2015-05-23 13:35:12 +02:00
{
if ( ! isNewFont() )
2015-05-23 13:35:12 +02:00
return;
int x1 = 1
, x2 = getWidth() + 1
, y1 = 0
, y2 = getHeight() + 1;
if ( FWidget* p = getParentWidget() )
setColor (wc.dialog_fg, p->getBackgroundColor());
else
setColor (wc.dialog_fg, wc.dialog_bg);
2015-05-23 13:35:12 +02:00
// clear on left side
for (register int y = 0; y < getHeight(); y++)
{
setPrintPos (x1 - 1, y1 + y + 1);
2015-05-23 13:35:12 +02:00
if ( double_flatline_mask.left[uLong(y)] )
print (fc::NF_border_line_left);
else
print (' ');
}
// clear on right side
for (register int y = 0; y < getHeight(); y++)
{
setPrintPos (x2, y1 + y + 1);
2015-05-23 13:35:12 +02:00
if ( double_flatline_mask.right[uLong(y)] )
print (fc::NF_rev_border_line_right);
else
print (' ');
}
2016-05-16 21:11:32 +02:00
// clear at top
setPrintPos (x1, y1);
2016-05-16 21:11:32 +02:00
for (register int x = 0; x < getWidth(); x++)
2016-05-16 21:11:32 +02:00
{
if ( double_flatline_mask.top[uLong(x)] )
print (fc::NF_border_line_upper);
2016-05-16 21:11:32 +02:00
else
print (' ');
2016-05-16 21:11:32 +02:00
}
// clear at bottom
setPrintPos (x1, y2);
2016-05-16 21:11:32 +02:00
for (register int x = 0; x < getWidth(); x++)
2016-05-16 21:11:32 +02:00
{
if ( double_flatline_mask.bottom[uLong(x)] )
print (fc::NF_border_line_bottom);
2016-05-16 21:11:32 +02:00
else
print (' ');
2016-05-16 21:11:32 +02:00
}
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::drawBorder (int x1, int y1, int x2, int y2)
2015-05-23 13:35:12 +02:00
{
if ( x1 > x2 )
std::swap (x1, x2);
2016-05-16 21:11:32 +02:00
if ( y1 > y2 )
std::swap (y1, y2);
2016-05-16 21:11:32 +02:00
if ( x1 < 1 )
x1 = 1;
if ( y1 < 1 )
y1 = 1;
if ( x2 > getWidth() )
x2 = getWidth();
if ( y2 > getHeight() )
y2 = getHeight();
if ( isNewFont() )
drawNewFontBox (x1, y1, x2, y2);
else
drawBox (x1, y1, x2, y2);
}
//----------------------------------------------------------------------
void FWidget::quit()
{
FApplication* fapp = static_cast<FApplication*>(rootObject);
fapp->exit(0);
2015-05-23 13:35:12 +02:00
}
// protected methods of FWidget
//----------------------------------------------------------------------
FVTerm::term_area* FWidget::getPrintArea()
{
// returns the print area of this object
if ( print_area )
return print_area;
else
{
FWidget* obj;
FWidget* p_obj = this;
do
{
obj = p_obj;
p_obj = static_cast<FWidget*>(obj->getParent());
}
while ( ! obj->vwin && ! obj->child_print_area && p_obj );
if ( obj->vwin )
{
print_area = obj->vwin;
return print_area;
}
else if ( obj->child_print_area )
{
print_area = obj->child_print_area;
return print_area;
}
}
return vdesktop;
}
//----------------------------------------------------------------------
void FWidget::addPreprocessingHandler ( FVTerm* instance
, FPreprocessingHandler handler )
{
if ( ! print_area )
FWidget::getPrintArea();
FVTerm::addPreprocessingHandler (instance, handler);
}
//----------------------------------------------------------------------
void FWidget::delPreprocessingHandler (FVTerm* instance)
{
if ( ! print_area )
FWidget::getPrintArea();
FVTerm::delPreprocessingHandler (instance);
}
//----------------------------------------------------------------------
bool FWidget::isChildPrintArea() const
{
FWidget* p_obj = static_cast<FWidget*>(getParent());
if ( p_obj
2017-11-26 22:37:18 +01:00
&& p_obj->child_print_area
&& p_obj->child_print_area == print_area )
return true;
else
return false;
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::setStatusBar (FStatusBar* sbar)
2015-05-23 13:35:12 +02:00
{
if ( ! sbar || statusbar == sbar )
return;
if ( statusbar )
delete statusbar;
statusbar = sbar;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
void FWidget::setMenuBar (FMenuBar* mbar)
2015-05-23 13:35:12 +02:00
{
if ( ! mbar || menubar == mbar )
return;
if ( menubar )
delete menubar;
menubar = mbar;
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::adjustSize()
{
if ( ! isRootWidget() )
2015-05-23 13:35:12 +02:00
{
FWidget* p = getParentWidget();
if ( isWindowWidget() )
{
if ( ignore_padding && ! isDialogWidget() )
setTermOffset();
else
offset = rootObject->client_offset;
}
else if ( ignore_padding && p )
{
offset.setCoordinates ( p->getTermX() - 1
, p->getTermY() - 1
, p->getTermX() + p->getWidth() - 2
, p->getTermY() + p->getHeight() - 2 );
}
else if ( p )
offset = p->client_offset;
adjust_wsize = wsize;
2015-05-23 13:35:12 +02:00
}
2017-01-22 23:04:40 +01:00
// Move and shrink in case of lack of space
if ( ! hasChildPrintArea() )
insufficientSpaceAdjust();
2015-05-23 13:35:12 +02:00
client_offset.setCoordinates
(
getTermX() - 1 + padding.left,
getTermY() - 1 + padding.top,
getTermX() - 2 + getWidth() - padding.right,
getTermY() - 2 + getHeight() - padding.bottom
);
2015-05-23 13:35:12 +02:00
if ( hasChildren() )
{
constFObjectIterator iter, last;
iter = FObject::begin();
last = FObject::end();
while ( iter != last )
{
2017-06-11 17:47:50 +02:00
if ( (*iter)->isWidget() )
{
FWidget* widget = static_cast<FWidget*>(*iter);
2017-06-11 17:47:50 +02:00
if ( ! widget->isWindowWidget() )
widget->adjustSize();
}
++iter;
}
}
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::adjustSizeGlobal()
2015-05-23 13:35:12 +02:00
{
if ( ! isRootWidget() )
2015-05-23 13:35:12 +02:00
{
getRootWidget()->adjustSizeGlobal();
2015-05-23 13:35:12 +02:00
return;
}
if ( window_list && ! window_list->empty() )
2015-05-23 13:35:12 +02:00
{
widgetList::const_iterator iter, last;
iter = window_list->begin();
last = window_list->end();
while ( iter != last )
2015-05-23 13:35:12 +02:00
{
(*iter)->adjustSize();
++iter;
}
}
}
//----------------------------------------------------------------------
bool FWidget::focusNextChild()
{
if ( isDialogWidget() )
return false;
if ( hasParent() )
2015-05-23 13:35:12 +02:00
{
FWidget* parent = getParentWidget();
if ( parent->hasChildren() && parent->numOfFocusableChildren() > 1 )
{
FObjectIterator iter, last;
iter = parent->begin();
last = parent->end();
2015-05-23 13:35:12 +02:00
while ( iter != last )
{
2017-06-11 17:47:50 +02:00
if ( ! (*iter)->isWidget() )
{
++iter;
continue;
}
FWidget* w = static_cast<FWidget*>(*iter);
2015-05-23 13:35:12 +02:00
if ( w == this )
{
2017-06-14 01:02:02 +02:00
FWidget* next = 0;
2017-09-15 01:31:02 +02:00
constFObjectIterator next_element;
next_element = iter;
do
{
++next_element;
if ( next_element == parent->end() )
next_element = parent->begin();
if ( ! (*next_element)->isWidget() )
continue;
next = static_cast<FWidget*>(*next_element);
2017-06-14 01:02:02 +02:00
} while ( ! next
2017-11-26 22:37:18 +01:00
|| ! next->isEnabled()
|| ! next->acceptFocus()
|| ! next->isVisible()
|| next->isWindowWidget() );
FFocusEvent out (fc::FocusOut_Event);
out.setFocusType(fc::FocusNextWidget);
FApplication::sendEvent(this, &out);
FFocusEvent cfo (fc::ChildFocusOut_Event);
cfo.setFocusType(fc::FocusNextWidget);
cfo.ignore();
FApplication::sendEvent(parent, &cfo);
if ( cfo.isAccepted() )
out.ignore();
if ( out.isAccepted() )
{
if ( next == this )
return false;
next->setFocus();
FFocusEvent cfi (fc::ChildFocusIn_Event);
FApplication::sendEvent(parent, &cfi);
FFocusEvent in (fc::FocusIn_Event);
in.setFocusType(fc::FocusNextWidget);
FApplication::sendEvent(next, &in);
if ( in.isAccepted() )
{
redraw();
next->redraw();
updateTerminal();
flush_out();
}
}
break;
}
++iter;
}
}
2015-05-23 13:35:12 +02:00
}
return true;
2015-05-23 13:35:12 +02:00
}
//----------------------------------------------------------------------
bool FWidget::focusPrevChild()
2015-05-23 13:35:12 +02:00
{
if ( isDialogWidget() )
return false;
2015-05-23 13:35:12 +02:00
if ( hasParent() )
{
FWidget* parent = getParentWidget();
if ( parent->hasChildren() && parent->numOfFocusableChildren() > 1 )
2015-05-23 13:35:12 +02:00
{
FObjectIterator iter, first;
iter = parent->end();
first = parent->begin();
do
{
--iter;
2017-06-11 17:47:50 +02:00
if ( ! (*iter)->isWidget() )
continue;
FWidget* w = static_cast<FWidget*>(*iter);
if ( w == this )
{
2017-06-14 01:02:02 +02:00
FWidget* prev = 0;
2017-09-15 01:31:02 +02:00
constFObjectIterator prev_element;
prev_element = iter;
2015-05-23 13:35:12 +02:00
do
{
2017-06-11 17:47:50 +02:00
if ( ! (*prev_element)->isWidget() )
{
--prev_element;
continue;
}
if ( prev_element == parent->begin() )
prev_element = parent->end();
2015-05-23 13:35:12 +02:00
--prev_element;
prev = static_cast<FWidget*>(*prev_element);
2017-06-14 01:02:02 +02:00
} while ( ! prev
2017-11-26 22:37:18 +01:00
|| ! prev->isEnabled()
|| ! prev->acceptFocus()
|| ! prev->isVisible()
|| prev->isWindowWidget() );
2015-05-23 13:35:12 +02:00
FFocusEvent out (fc::FocusOut_Event);
out.setFocusType(fc::FocusPreviousWidget);
FApplication::sendEvent(this, &out);
2015-05-23 13:35:12 +02:00
FFocusEvent cfo (fc::ChildFocusOut_Event);
cfo.setFocusType(fc::FocusPreviousWidget);
cfo.ignore();
FApplication::sendEvent(parent, &cfo);
if ( cfo.isAccepted() )
out.ignore();
if ( out.isAccepted() )
{
if ( prev == this )
return false;
prev->setFocus();
FFocusEvent cfi (fc::ChildFocusIn_Event);
FApplication::sendEvent(parent, &cfi);
FFocusEvent in (fc::FocusIn_Event);
in.setFocusType(fc::FocusPreviousWidget);
FApplication::sendEvent(prev, &in);
if ( in.isAccepted() )
{
redraw();
prev->redraw();
updateTerminal();
flush_out();
}
}
break;
}
}
while ( iter != first );
}
2015-05-23 13:35:12 +02:00
}
return true;
}
//----------------------------------------------------------------------
bool FWidget::event (FEvent* ev)
{
switch ( ev->type() )
2015-05-23 13:35:12 +02:00
{
case fc::KeyPress_Event:
KeyPressEvent ( static_cast<FKeyEvent*>(ev) );
break;
2015-05-23 13:35:12 +02:00
case fc::KeyUp_Event:
onKeyUp ( static_cast<FKeyEvent*>(ev) );
break;
case fc::KeyDown_Event:
KeyDownEvent ( static_cast<FKeyEvent*>(ev) );
break;
2015-05-23 13:35:12 +02:00
case fc::MouseDown_Event:
onMouseDown ( static_cast<FMouseEvent*>(ev) );
break;
case fc::MouseUp_Event:
onMouseUp ( static_cast<FMouseEvent*>(ev) );
break;
case fc::MouseDoubleClick_Event:
onMouseDoubleClick ( static_cast<FMouseEvent*>(ev) );
break;
case fc::MouseWheel_Event:
onWheel ( static_cast<FWheelEvent*>(ev) );
break;
case fc::MouseMove_Event:
onMouseMove ( static_cast<FMouseEvent*>(ev) );
break;
2015-09-20 05:44:50 +02:00
case fc::FocusIn_Event:
onFocusIn ( static_cast<FFocusEvent*>(ev) );
2015-09-20 05:44:50 +02:00
break;
case fc::FocusOut_Event:
onFocusOut ( static_cast<FFocusEvent*>(ev) );
break;
case fc::ChildFocusIn_Event:
onChildFocusIn ( static_cast<FFocusEvent*>(ev) );
break;
case fc::ChildFocusOut_Event:
onChildFocusOut ( static_cast<FFocusEvent*>(ev) );
break;
case fc::Accelerator_Event:
onAccel ( static_cast<FAccelEvent*>(ev) );
break;
case fc::Resize_Event:
onResize ( static_cast<FResizeEvent*>(ev) );
break;
case fc::Show_Event:
onShow ( static_cast<FShowEvent*>(ev) );
break;
case fc::Hide_Event:
onHide ( static_cast<FHideEvent*>(ev) );
break;
case fc::Close_Event:
onClose ( static_cast<FCloseEvent*>(ev) );
break;
case fc::Timer_Event:
onTimer ( static_cast<FTimerEvent*>(ev) );
break;
default:
return false;
}
return true;
}
//----------------------------------------------------------------------
void FWidget::onKeyPress (FKeyEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onKeyUp (FKeyEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onKeyDown (FKeyEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onMouseDown (FMouseEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onMouseUp (FMouseEvent*)
{ }
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::onMouseDoubleClick (FMouseEvent*)
{ }
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::onWheel (FWheelEvent*)
{ }
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::onMouseMove (FMouseEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onFocusIn (FFocusEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onFocusOut (FFocusEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onChildFocusIn (FFocusEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onChildFocusOut (FFocusEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onAccel (FAccelEvent*)
{ }
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::onResize (FResizeEvent* ev)
{
rootObject->resize();
rootObject->redraw();
ev->accept();
}
//----------------------------------------------------------------------
void FWidget::onShow (FShowEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onHide (FHideEvent*)
{ }
//----------------------------------------------------------------------
void FWidget::onClose (FCloseEvent* ev)
{
ev->accept();
}
// private methods of FWidget
//----------------------------------------------------------------------
void FWidget::init()
{
2017-08-12 22:55:29 +02:00
try
{
// Initialize widget lists
window_list = new widgetList();
dialog_list = new widgetList();
always_on_top_list = new widgetList();
close_widget = new widgetList();
}
catch (const std::bad_alloc& ex)
{
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
return;
}
char* cursor_off_str = disableCursor();
if ( cursor_off_str && std::strlen(cursor_off_str) > 0 )
hideable = true;
else
hideable = false;
visible_cursor = ! hideable;
2017-08-12 22:55:29 +02:00
// Determine width and height of the terminal
detectTermSize();
wsize.setRect(1, 1, getDesktopWidth(), getDesktopHeight());
adjust_wsize = wsize;
offset.setRect(0, 0, getDesktopWidth(), getDesktopHeight());
client_offset = offset;
2015-05-23 13:35:12 +02:00
double_flatline_mask.top.resize (uLong(getWidth()), false);
double_flatline_mask.right.resize (uLong(getHeight()), false);
double_flatline_mask.bottom.resize (uLong(getWidth()), false);
double_flatline_mask.left.resize (uLong(getHeight()), false);
// Initialize default widget colors
setColorTheme();
// Default foreground and background color of the desktop/terminal
foreground_color = wc.term_fg;
background_color = wc.term_bg;
2016-11-27 19:16:52 +01:00
init_desktop = false;
2017-08-12 22:55:29 +02:00
try
{
accelerator_list = new Accelerators();
}
catch (const std::bad_alloc& ex)
{
std::cerr << "not enough memory to alloc " << ex.what() << std::endl;
}
}
//----------------------------------------------------------------------
void FWidget::finish()
{
delete accelerator_list;
accelerator_list = 0;
if ( close_widget )
{
delete close_widget;
close_widget = 0;
}
2015-05-23 13:35:12 +02:00
if ( dialog_list )
{
delete dialog_list;
dialog_list = 0;
}
if ( always_on_top_list )
{
delete always_on_top_list;
always_on_top_list = 0;
}
if ( window_list )
{
delete window_list;
window_list = 0;
2015-05-23 13:35:12 +02:00
}
}
2017-01-22 23:04:40 +01:00
//----------------------------------------------------------------------
inline void FWidget::insufficientSpaceAdjust()
{
// Move and shrink widget if there is not enough space available
if ( isWindowWidget() )
return;
// move left if not enough space
while ( getTermX() + getWidth() - padding.right > offset.getX2() + 2 )
2017-01-22 23:04:40 +01:00
{
adjust_wsize.x1_ref()--;
adjust_wsize.x2_ref()--;
if ( adjust_wsize.x1_ref() < 1 )
adjust_wsize.x1_ref() = 1;
}
// move up if not enough space
while ( getTermY() + getHeight() - padding.bottom > offset.getY2() + 2 )
2017-01-22 23:04:40 +01:00
{
adjust_wsize.y1_ref()--;
adjust_wsize.y2_ref()--;
if ( adjust_wsize.y1_ref() < 1 )
adjust_wsize.y1_ref() = 1;
}
// reduce the width if not enough space
while ( offset.getX1() + getWidth() - 1 > offset.getX2() )
2017-01-22 23:04:40 +01:00
adjust_wsize.x2_ref()--;
if ( getWidth() < size_hints.min_width )
adjust_wsize.setWidth(size_hints.min_width);
if ( getWidth() <= 0 )
adjust_wsize.setWidth(1);
// reduce the height if not enough space
while ( offset.getY1() + getHeight() - 1 > offset.getY2() )
2017-01-22 23:04:40 +01:00
adjust_wsize.y2_ref()--;
if ( getHeight() < size_hints.min_height )
adjust_wsize.setWidth(size_hints.min_height);
if ( getHeight() <= 0 )
adjust_wsize.setHeight(1);
}
//----------------------------------------------------------------------
void FWidget::KeyPressEvent (FKeyEvent* kev)
{
bool accpt_focus = false;
if ( kev->key() == fc::Fkey_tab )
accpt_focus = focusNextChild();
else if ( kev->key() == fc::Fkey_btab )
accpt_focus = focusPrevChild();
if ( accpt_focus )
return;
FWidget* widget = this;
while ( widget )
{
widget->onKeyPress(kev);
if ( ! kev->isAccepted() )
{
if ( kev->key() == fc::Fkey_right
|| kev->key() == fc::Fkey_down )
accpt_focus = focusNextChild();
else if ( kev->key() == fc::Fkey_left
|| kev->key() == fc::Fkey_up )
accpt_focus = focusPrevChild();
if ( accpt_focus )
return;
}
if ( kev->isAccepted() || widget->isRootWidget() )
return;
widget = widget->getParentWidget();
}
}
//----------------------------------------------------------------------
void FWidget::KeyDownEvent (FKeyEvent* kev)
{
FWidget* widget = this;
while ( widget )
{
widget->onKeyDown(kev);
if ( kev->isAccepted() || widget->isRootWidget() )
break;
widget = widget->getParentWidget();
}
}
2015-05-23 13:35:12 +02:00
//----------------------------------------------------------------------
void FWidget::draw()
{ }
//----------------------------------------------------------------------
void FWidget::drawWindows()
{
// redraw windows
FOptiAttr::char_data default_char;
default_char.code = ' ';
default_char.fg_color = fc::Black;
default_char.bg_color = fc::Black;
default_char.attr.byte[0] = 0;
default_char.attr.byte[1] = 0;
if ( ! window_list || window_list->empty() )
return;
widgetList::const_iterator iter, last;
iter = window_list->begin();
last = window_list->end();
while ( iter != last )
{
if ( (*iter)->isVisible() )
{
term_area* win = (*iter)->getVWin();
int w = win->width + win->right_shadow;
int h = win->height + win->bottom_shadow;
std::fill_n (win->text, w * h, default_char);
(*iter)->redraw();
}
++iter;
}
}
//----------------------------------------------------------------------
void FWidget::drawChildren()
{
// draw child elements
if ( ! hasChildren() )
return;
constFObjectIterator iter, last;
iter = FObject::begin();
last = FObject::end();
while ( iter != last )
{
if ( (*iter)->isWidget() )
{
FWidget* widget = static_cast<FWidget*>(*iter);
if ( widget->isVisible() && ! widget->isWindowWidget() )
widget->redraw();
}
++iter;
}
}
//----------------------------------------------------------------------
void FWidget::drawTransparentShadow (int x1, int y1, int x2, int y2)
{
// transparent shadow
setPrintPos (x2 + 1, y1);
setTransparent();
print (" ");
unsetTransparent();
setColor (wc.shadow_bg, wc.shadow_fg);
setTransShadow();
for (int i = 1; i < getHeight(); i++)
{
setPrintPos (x2 + 1, y1 + i);
print (" ");
}
unsetTransShadow();
setPrintPos (x1, y2 + 1);
setTransparent();
print (" ");
unsetTransparent();
setColor (wc.shadow_bg, wc.shadow_fg);
setTransShadow();
for (int i = 2; i <= getWidth() + 1; i++)
print (' ');
unsetTransShadow();
if ( isMonochron() )
setReverse(false);
}
//----------------------------------------------------------------------
void FWidget::drawBlockShadow (int x1, int y1, int x2, int y2)
{
// non-transparent shadow
int block;
if ( no_shadow_character )
return;
setPrintPos (x2 + 1, y1);
if ( isWindowWidget() )
{
setColor (wc.shadow_fg, wc.shadow_bg);
setInheritBackground(); // current background color will be ignored
}
else if ( FWidget* p = getParentWidget() )
setColor (wc.shadow_fg, p->getBackgroundColor());
block = fc::FullBlock; // █
print (fc::LowerHalfBlock); // ▄
if ( isWindowWidget() )
unsetInheritBackground();
for (int i = 1; i < getHeight(); i++)
{
setPrintPos (x2 + 1, y1 + i);
print (block); // █
}
setPrintPos (x1 + 1, y2 + 1);
if ( isWindowWidget() )
setInheritBackground();
for (int i = 1; i <= getWidth(); i++)
print (fc::UpperHalfBlock); // ▀
if ( isWindowWidget() )
unsetInheritBackground();
}
//----------------------------------------------------------------------
inline void FWidget::drawBox (int x1, int y1, int x2, int y2)
{
// Use box-drawing characters to draw a border
setPrintPos (x1, y1);
print (fc::BoxDrawingsDownAndRight); // ┌
for (int x = x1 + 1; x < x2; x++)
print (fc::BoxDrawingsHorizontal); // ─
print (fc::BoxDrawingsDownAndLeft); // ┐
for (int y = y1 + 1; y < y2; y++)
{
setPrintPos (x1, y);
print (fc::BoxDrawingsVertical); // │
setPrintPos (x2, y);
print (fc::BoxDrawingsVertical); // │
}
setPrintPos (x1, y2);
print (fc::BoxDrawingsUpAndRight); // └
for (int x = x1 + 1; x < x2; x++)
print (fc::BoxDrawingsHorizontal); // ─
print (fc::BoxDrawingsUpAndLeft); // ┘
for (int x = x1 + 1; x < x2; x++)
{
setPrintPos (x, y1);
print (fc::BoxDrawingsHorizontal); // ─
setPrintPos (x, y2);
print (fc::BoxDrawingsHorizontal); // ─
}
}
//----------------------------------------------------------------------
inline void FWidget::drawNewFontBox (int x1, int y1, int x2, int y2)
{
// Use new graphical font characters to draw a border
setPrintPos (x1, y1);
print (fc::NF_border_corner_middle_upper_left); // ┌
for (int x = x1 + 1; x < x2; x++)
print (fc::BoxDrawingsHorizontal); // ─
print (fc::NF_border_corner_middle_upper_right); // ┐
for (int y = y1 + 1; y <= y2; y++)
{
setPrintPos (x1, y);
print (fc::NF_border_line_left); // border left ⎸
setPrintPos (x2, y);
print (fc::NF_rev_border_line_right); // border right⎹
}
setPrintPos (x1, y2);
print (fc::NF_border_corner_middle_lower_left); // └
for (int x = x1 + 1; x < x2; x++)
print (fc::BoxDrawingsHorizontal); // ─
print (fc::NF_border_corner_middle_lower_right); // ┘
}
//----------------------------------------------------------------------
void FWidget::setColorTheme()
{
// Sets the default color theme
if ( getMaxColor() < 16 ) // for 8 color mode
{
wc.set8ColorTheme();
}
else
{
wc.set16ColorTheme();
if ( isKdeTerminal() )
wc.term_bg = fc::SteelBlue3;
}
}