From c43a7f9badd914067e7d5147e8e690eb9efab087 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Thu, 29 Sep 2016 04:29:12 +0200 Subject: [PATCH] The window size is now changeable with the mouse --- ChangeLog | 4 + doc/TODO | 1 - src/fcharmap.h | 4 - src/fdialog.cpp | 262 +++++++++++++++++++++++++++++++++++++++++----- src/fdialog.h | 2 + src/fenum.h | 4 - src/flineedit.cpp | 4 +- src/flistbox.cpp | 4 +- src/frect.cpp | 7 ++ src/frect.h | 21 ++++ src/fstring.cpp | 38 ++++++- src/fstring.h | 9 +- src/fterm.cpp | 11 +- src/ftextview.cpp | 90 +++++++++++++++- src/ftextview.h | 2 + src/fwidget.cpp | 9 +- src/fwidget.h | 11 +- src/fwindow.cpp | 11 ++ src/fwindow.h | 5 +- test/ui.cpp | 1 + test/windows.cpp | 101 +++++++++++++++--- 21 files changed, 526 insertions(+), 75 deletions(-) diff --git a/ChangeLog b/ChangeLog index 74bcbe4d..03c2b909 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-09-28 Markus Gans + * The size is now dynamically changeable with the mouse + in a resizable window. + 2016-09-26 Markus Gans * FLabel now transmits the Click events to the parent widget diff --git a/doc/TODO b/doc/TODO index 77ed3d74..f478b54c 100644 --- a/doc/TODO +++ b/doc/TODO @@ -20,7 +20,6 @@ Missing Features └──► tmp --------------------------------------- -- A possibility to change the window size dynamically with the mouse - Add a scrolling area with on-demand scroll bars for FButtonGroup - Adding for flexible layouts a FGrid widget container that organizes its child widgets in rows and columns diff --git a/src/fcharmap.h b/src/fcharmap.h index 371259c0..431fdf97 100644 --- a/src/fcharmap.h +++ b/src/fcharmap.h @@ -57,10 +57,6 @@ static uInt character[][fc::NUM_OF_ENCODINGS] = {0x25bc, '.', 0x1f, 'v'}, // ▼ - BlackDownPointingTriangle {0x25ba, '+', 0x10, '>'}, // ► - BlackRightPointingPointer {0x25c4, ',', 0x11, '<'}, // ◄ - BlackLeftPointingPointer - {0x25E2,'\\', '\\','\\'}, // ◢ - BlackLowerLightTriangle - {0x25E3, '/', '/', '/'}, // ◣ - BlackLowerLeftTriangle - {0x25E4,'\\', '\\','\\'}, // ◤ - BlackUpperLeftTriangle - {0x25E5, '/', '/', '/'}, // ◥ - BlackUpperRightTriangle {0x1ab4, 0, 0xb4, 0}, // ⊐ - NF_rev_left_arrow2 {0x1ab5, 0, 0xb5, 0}, // ► - NF_rev_right_arrow2 {0x1ab7, 0, 0xb7, 0}, // ) - NF_radio_button3 diff --git a/src/fdialog.cpp b/src/fdialog.cpp index 1ce9ce95..9d8026a2 100644 --- a/src/fdialog.cpp +++ b/src/fdialog.cpp @@ -19,6 +19,7 @@ FDialog::FDialog(FWidget* parent) , zoom_button_pressed(false) , zoom_button_active(false) , titlebar_click_pos() + , resize_click_pos() , old_geometry() , dialog_menu() , dgl_menuitem() @@ -36,6 +37,7 @@ FDialog::FDialog (const FString& txt, FWidget* parent) , zoom_button_pressed(false) , zoom_button_active(false) , titlebar_click_pos() + , resize_click_pos() , old_geometry() , dialog_menu() , dgl_menuitem() @@ -95,6 +97,7 @@ void FDialog::init() setDialogWidget(); // initialize geometry values setGeometry (1, 1, 10, 10, false); + setMinimumSize (15, 4); createArea (vwin); addDialog(this); addWindow(this); @@ -158,8 +161,10 @@ void FDialog::drawBorder() int y1 = 2; int y2 = 1 + getHeight() - 1; - //if ( resize ) - // setColor (wc.dialog_resize_fg, getBackgroundColor()); + if ( resize_click_pos.isNull() || isZoomed() ) + setColor(); + else + setColor (wc.dialog_resize_fg, getBackgroundColor()); if ( isNewFont() ) { @@ -281,7 +286,7 @@ void FDialog::drawTitleBar() zoom_btn = 3; length = int(tb_text.getLength()); - i = getWidth() - length - menu_btn - zoom_btn; + i = getWidth() - length - menu_btn - zoom_btn; i = int(i/2); for (x=1; x <= i; x++) @@ -289,7 +294,15 @@ void FDialog::drawTitleBar() // the title bar text if ( tb_text ) - print (tb_text); + { + if ( length <= getWidth() - menu_btn - zoom_btn ) + print (tb_text); + else + { + print (tb_text.left(getWidth() - menu_btn - zoom_btn - 2)); + print (".."); + } + } // fill the rest of the bar for (; x+1+length < getWidth()-zoom_btn-1; x++) @@ -571,7 +584,15 @@ void FDialog::onKeyPress (FKeyEvent* ev) if ( ! isEnabled() ) return; - if ( ev->key() == fc::Fckey_caret ) // Ctrl+^ + // cancel resize + if ( ! resize_click_pos.isNull() ) + { + resize_click_pos.setPoint (0,0); + drawBorder(); + updateTerminal(); + } + + if ( ev->key() == fc::Fckey_caret ) // Ctrl+^ (Ctrl+6) { ev->accept(); // open the titlebar menu @@ -637,18 +658,48 @@ void FDialog::onMouseDown (FMouseEvent* ev) // click on titlebar menu button if ( mouse_x < 4 && mouse_y == 1 ) openMenu(); - else if ( mouse_x > getWidth()-zoom_btn && mouse_y == 1 ) + else if ( mouse_x > getWidth()-zoom_btn && mouse_y == 1 ) { zoom_button_pressed = true; zoom_button_active = true; drawTitleBar(); } + + // click on the lower right resize corner + if ( isResizeable() + && ( (mouse_x == getWidth() && mouse_y == getHeight()) + || (mouse_x == getWidth()-1 && mouse_y == getHeight()) + || (mouse_x == getWidth() && mouse_y == getHeight()-1) ) ) + { + resize_click_pos = ev->getTermPos(); + FPoint lower_right_pos = getTermGeometry().getLowerRightPos(); + + if ( ev->getTermPos() != lower_right_pos ) + { + FPoint deltaPos = ev->getTermPos() - lower_right_pos; + int w = lower_right_pos.getX() + deltaPos.getX() - getTermX() + 1; + int h = lower_right_pos.getY() + deltaPos.getY() - getTermY() + 1; + setSize (w, h); + } + else + drawBorder(); + } + else + resize_click_pos.setPoint (0,0); } else // ev->getButton() != fc::LeftButton { // click on titlebar menu button if ( mouse_x < 4 && mouse_y == 1 && dialog_menu->isVisible() ) leaveMenu(); // close menu + + // cancel resize + if ( ! resize_click_pos.isNull() ) + { + resize_click_pos.setPoint (0,0); + drawBorder(); + updateTerminal(); + } } if ( ev->getButton() == fc::RightButton ) @@ -679,8 +730,6 @@ void FDialog::onMouseDown (FMouseEvent* ev) //---------------------------------------------------------------------- void FDialog::onMouseUp (FMouseEvent* ev) { - int titlebar_x = titlebar_click_pos.getX(); - int titlebar_y = titlebar_click_pos.getY(); int zoom_btn; if ( (flags & fc::resizeable) == 0 ) @@ -692,8 +741,10 @@ void FDialog::onMouseUp (FMouseEvent* ev) if ( ev->getButton() == fc::LeftButton ) { - int mouse_x = ev->getX(); - int mouse_y = ev->getY(); + int mouse_x = ev->getX(); + int mouse_y = ev->getY(); + int titlebar_x = titlebar_click_pos.getX(); + int titlebar_y = titlebar_click_pos.getY(); if ( ! titlebar_click_pos.isNull() && titlebar_x > getTermX() + 3 @@ -723,6 +774,48 @@ void FDialog::onMouseUp (FMouseEvent* ev) zoomWindow(); setZoomItem(); } + + // resize the dialog + if ( isResizeable() && ! resize_click_pos.isNull() ) + { + FWidget* r = getRootWidget(); + resize_click_pos = ev->getTermPos(); + int x2 = resize_click_pos.getX(); + int y2 = resize_click_pos.getY(); + int x2_offset = 0; + int y2_offset = 0; + + if ( r ) + { + x2_offset = r->getLeftPadding(); + y2_offset = r->getTopPadding(); + } + + if ( ev->getTermPos() != getTermGeometry().getLowerRightPos() ) + { + int w, h; + FPoint deltaPos = ev->getTermPos() - resize_click_pos; + + if ( x2 - x2_offset <= getMaxWidth() ) + w = resize_click_pos.getX() + deltaPos.getX() - getTermX() + 1; + else + w = getMaxWidth() - getTermX() + x2_offset + 1; + + if ( y2 - y2_offset <= getMaxHeight() ) + h = resize_click_pos.getY() + deltaPos.getY() - getTermY() + 1; + else + h = getMaxHeight() - getTermY() + y2_offset + 1; + + setSize (w, h); + } + + // reset the border color + resize_click_pos.setPoint (0,0); + + // redraw() is required to draw the standard (black) border + // and client objects with ignorePadding() option. + redraw(); + } } if ( zoom_button_pressed || zoom_button_active ) @@ -778,16 +871,44 @@ void FDialog::onMouseMove (FMouseEvent* ev) } if ( mouse_x > getWidth() - zoom_btn && mouse_y == 1 && zoom_button_active ) - { zoom_button_pressed = true; - drawTitleBar(); - } else if ( zoom_button_pressed ) - { zoom_button_pressed = false; - drawTitleBar(); - } + drawTitleBar(); + + // resize the dialog + if ( isResizeable() && ! resize_click_pos.isNull() + && ev->getTermPos() != getTermGeometry().getLowerRightPos() ) + { + FWidget* r = getRootWidget(); + resize_click_pos = ev->getTermPos(); + int x2 = resize_click_pos.getX(); + int y2 = resize_click_pos.getY(); + int x2_offset = 0; + int y2_offset = 0; + + if ( r ) + { + x2_offset = r->getLeftPadding(); + y2_offset = r->getTopPadding(); + } + + int w, h; + FPoint deltaPos = ev->getTermPos() - resize_click_pos; + + if ( x2 - x2_offset <= getMaxWidth() ) + w = resize_click_pos.getX() + deltaPos.getX() - getTermX() + 1; + else + w = getMaxWidth() - getTermX() + x2_offset + 1; + + if ( y2 - y2_offset <= getMaxHeight() ) + h = resize_click_pos.getY() + deltaPos.getY() - getTermY() + 1; + else + h = getMaxHeight() - getTermY() + y2_offset + 1; + + setSize (w, h); + } } } @@ -994,18 +1115,22 @@ int FDialog::exec() //---------------------------------------------------------------------- void FDialog::move (const FPoint& pos) { - move( pos.getX(), pos.getY() ); + move ( pos.getX(), pos.getY() ); } //---------------------------------------------------------------------- void FDialog::move (int x, int y) { - int dx, dy, old_x, old_y, rsw, bsh; + int dx, dy, old_x, old_y, rsw, bsh, width, height; if ( getX() == x && getY() == y ) return; - if ( x+getWidth() < 1 || x > getColumnNumber() || y < 1 || y > getLineNumber() ) + width = getWidth(); + height = getHeight(); + + // Avoid to move widget completely outside the terminal + if ( x+width < 1 || x > getColumnNumber() || y < 1 || y > getLineNumber() ) return; if ( isZoomed() ) @@ -1018,13 +1143,15 @@ void FDialog::move (int x, int y) const FPoint& shadow = getShadow(); rsw = shadow.getX(); // right shadow width; bsh = shadow.getY(); // bottom shadow height - old_geometry = getGeometryWithShadow(); + old_geometry = getTermGeometryWithShadow(); + // move to the new position FWidget::move(x,y); setPos(x, y, false); - putArea (getTermPos(), vwin);updateTerminal(); + putArea (getTermPos(), vwin); - if ( getGeometry().overlap(old_geometry) ) + // restoring the non-covered terminal areas + if ( getTermGeometry().overlap(old_geometry) ) { // dx > 0 : move left // dx = 0 : move vertical @@ -1036,25 +1163,26 @@ void FDialog::move (int x, int y) if ( dx > 0 ) { if ( dy > 0 ) - restoreVTerm (old_x+getWidth()+rsw-dx, old_y, dx, getHeight()+bsh-dy); + restoreVTerm (old_x+width+rsw-dx, old_y, dx, getHeight()+bsh-dy); else - restoreVTerm (old_x+getWidth()+rsw-dx, old_y+abs(dy), dx, getHeight()+bsh-abs(dy)); + restoreVTerm (old_x+width+rsw-dx, old_y+abs(dy), dx, height+bsh-abs(dy)); } else { if ( dy > 0 ) - restoreVTerm (old_x, old_y, abs(dx), getHeight()+bsh-dy); + restoreVTerm (old_x, old_y, abs(dx), height+bsh-dy); else - restoreVTerm (old_x, old_y+abs(dy), abs(dx), getHeight()+bsh-abs(dy)); + restoreVTerm (old_x, old_y+abs(dy), abs(dx), height+bsh-abs(dy)); } + if ( dy > 0 ) - restoreVTerm (old_x, old_y+getHeight()+bsh-dy, getWidth()+rsw, dy); + restoreVTerm (old_x, old_y+height+bsh-dy, width+rsw, dy); else - restoreVTerm (old_x, old_y, getWidth()+rsw, abs(dy)); + restoreVTerm (old_x, old_y, width+rsw, abs(dy)); } else { - restoreVTerm (old_x, old_y, getWidth()+rsw, getHeight()+bsh); + restoreVTerm (old_geometry); } // handle overlaid windows @@ -1094,6 +1222,82 @@ void FDialog::move (int x, int y) updateTerminal(); } +//---------------------------------------------------------------------- +void FDialog::setSize (int w, int h, bool adjust) +{ + int x, y, dw, dh, old_width, old_height, rsw, bsh; + + if ( getWidth() == w && getHeight() == h ) + return; + + if ( isZoomed() ) + return; + + x = getTermX(); + y = getTermY(); + old_width = getWidth(); + old_height = getHeight(); + dw = old_width - w; + dh = old_height - h; + const FPoint& shadow = getShadow(); + rsw = shadow.getX(); // right shadow width; + bsh = shadow.getY(); // bottom shadow height + + FWindow::setSize (w, h, adjust); + + // get adjust width and height + w = getWidth(); + h = getHeight(); + + // dw > 0 : scale down width + // dw = 0 : scale only height + // dw < 0 : scale up width + // dh > 0 : scale down height + // dh = 0 : scale only width + // dh < 0 : scale up height + + // restoring the non-covered terminal areas + if ( dw > 0 ) + restoreVTerm (x+w+rsw, y, dw, h+bsh+dh); // restore right + + if ( dh > 0 ) + restoreVTerm (x, y+h+bsh, w+rsw+dw, dh); // restore bottom + + redraw(); + + // handle overlaid windows + if ( window_list && ! window_list->empty() ) + { + bool overlaid = false; + widgetList::const_iterator iter, end; + iter = window_list->begin(); + end = window_list->end(); + + while ( iter != end ) + { + if ( overlaid ) + putArea ((*iter)->getTermPos(), (*iter)->getVWin()); + + if ( vwin == (*iter)->getVWin() ) + overlaid = true; + + ++iter; + } + } + + // set the cursor to the focus widget + FWidget* focus_widget = FWidget::getFocusWidget(); + if ( focus_widget + && focus_widget->isVisible() + && focus_widget->hasVisibleCursor() ) + { + FPoint cursor_pos = focus_widget->getCursorPos(); + + if ( ! focus_widget->setCursorPos(cursor_pos) ) + hideCursor(); + } +} + //---------------------------------------------------------------------- void FDialog::activateDialog() { diff --git a/src/fdialog.h b/src/fdialog.h index 975761dd..f5e44c71 100644 --- a/src/fdialog.h +++ b/src/fdialog.h @@ -55,6 +55,7 @@ class FDialog : public FWindow bool zoom_button_pressed; bool zoom_button_active; FPoint titlebar_click_pos; + FPoint resize_click_pos; FRect old_geometry; // required by move() FMenu* dialog_menu; FMenuItem* dgl_menuitem; @@ -108,6 +109,7 @@ class FDialog : public FWindow int exec(); void move (const FPoint&); void move (int, int); + void setSize (int, int, bool = true); bool setFocus (bool); bool setFocus(); diff --git a/src/fenum.h b/src/fenum.h index b2fbffac..280f8190 100644 --- a/src/fenum.h +++ b/src/fenum.h @@ -166,10 +166,6 @@ class fc LowerHalfBlock = 0x2584, // ▄ LeftHalfBlock = 0x258c, // ▌ RightHalfBlock = 0x2590, // ▐ - BlackLowerLightTriangle = 0x25E2, // ◢ - BlackLowerLeftTriangle = 0x25E3, // ◣ - BlackUpperLeftTriangle = 0x25E4, // ◤ - BlackUpperRightTriangle = 0x25E5, // ◥ NF_rev_left_arrow2 = 0x1ab4, // ⊐ NF_rev_right_arrow2 = 0x1ab5, // ► NF_radio_button3 = 0x1ab7, // ) diff --git a/src/flineedit.cpp b/src/flineedit.cpp index 9a338005..6d8c3dee 100644 --- a/src/flineedit.cpp +++ b/src/flineedit.cpp @@ -690,7 +690,7 @@ void FLineEdit::onTimer (FTimerEvent*) { int len = int(text.getLength()); - switch ( drag_scroll ) + switch ( int(drag_scroll) ) { case FLineEdit::noScroll: return; @@ -731,6 +731,8 @@ void FLineEdit::onTimer (FTimerEvent*) if ( cursor_pos > len ) cursor_pos = len; + break; + default: break; } diff --git a/src/flistbox.cpp b/src/flistbox.cpp index 8e8095b0..c626894c 100644 --- a/src/flistbox.cpp +++ b/src/flistbox.cpp @@ -1257,7 +1257,7 @@ void FListBox::onTimer (FTimerEvent*) int current_before = current; int yoffset_before = yoffset; - switch ( drag_scroll ) + switch ( int(drag_scroll) ) { case FListBox::noScroll: return; @@ -1301,6 +1301,8 @@ void FListBox::onTimer (FTimerEvent*) if ( yoffset > element_count - getHeight() + 2 ) yoffset = element_count - getHeight() + 2; + break; + default: break; } diff --git a/src/frect.cpp b/src/frect.cpp index 39b7b552..ba219c88 100644 --- a/src/frect.cpp +++ b/src/frect.cpp @@ -101,6 +101,13 @@ void FRect::setHeight (int h) Y2 = short(Y1 + h - 1); } +//---------------------------------------------------------------------- +void FRect::setSize (int w, int h) +{ + X2 = short(X1 + w - 1); + Y2 = short(Y1 + h - 1); +} + //---------------------------------------------------------------------- void FRect::setRect (const FRect& r) { diff --git a/src/frect.h b/src/frect.h index 3589c8f1..d2eda96b 100644 --- a/src/frect.h +++ b/src/frect.h @@ -45,6 +45,10 @@ class FRect int getX() const; int getY() const; FPoint getPos() const; + FPoint getUpperLeftPos() const; + FPoint getUpperRightPos() const; + FPoint getLowerLeftPos() const; + FPoint getLowerRightPos() const; int getWidth() const; int getHeight() const; @@ -62,6 +66,7 @@ class FRect void setPos (const FPoint&); void setWidth (int); void setHeight (int); + void setSize (int, int); void setRect (const FRect&); void setRect (int, int, int, int); void setCoordinates (const FPoint&, const FPoint&); @@ -134,6 +139,22 @@ inline int FRect::getY() const inline FPoint FRect::getPos() const { return FPoint(X1,Y1); } +//---------------------------------------------------------------------- +inline FPoint FRect::getUpperLeftPos() const +{ return FPoint(X1,Y1); } + +//---------------------------------------------------------------------- +inline FPoint FRect::getUpperRightPos() const +{ return FPoint(X2,Y1); } + +//---------------------------------------------------------------------- +inline FPoint FRect::getLowerLeftPos() const +{ return FPoint(X1,Y2); } + +//---------------------------------------------------------------------- +inline FPoint FRect::getLowerRightPos() const +{ return FPoint(X2,Y2); } + //---------------------------------------------------------------------- inline int FRect::getWidth() const { return X2 - X1 + 1; } diff --git a/src/fstring.cpp b/src/fstring.cpp index 28e426f6..52734864 100644 --- a/src/fstring.cpp +++ b/src/fstring.cpp @@ -1272,7 +1272,16 @@ FString FString::trim() const } //---------------------------------------------------------------------- -FString FString::left(uInt len) const +FString FString::left (int len) const +{ + if ( len > 0) + return left (uInt(len)); + else + return left (uInt(0)); +} + +//---------------------------------------------------------------------- +FString FString::left (uInt len) const { register wchar_t* p; FString s(string); @@ -1290,7 +1299,16 @@ FString FString::left(uInt len) const } //---------------------------------------------------------------------- -FString FString::right(uInt len) const +FString FString::right (int len) const +{ + if ( len > 0) + return right (uInt(len)); + else + return right (uInt(0)); +} + +//---------------------------------------------------------------------- +FString FString::right (uInt len) const { register wchar_t* p; FString s(string); @@ -1308,7 +1326,21 @@ FString FString::right(uInt len) const } //---------------------------------------------------------------------- -FString FString::mid(uInt pos, uInt len) const +FString FString::mid (int pos, int len) const +{ + if ( pos > 0 ) + { + if ( len > 0 ) + return mid (uInt(pos), uInt(len)); + else + return mid (uInt(pos), uInt(0)); + } + else + return mid (uInt(0), uInt(0)); +} + +//---------------------------------------------------------------------- +FString FString::mid (uInt pos, uInt len) const { register wchar_t* p; register wchar_t* first; diff --git a/src/fstring.h b/src/fstring.h index 9f025c41..02f611f4 100644 --- a/src/fstring.h +++ b/src/fstring.h @@ -138,9 +138,12 @@ class FString FString rtrim() const; FString trim() const; - FString left(uInt) const; - FString right(uInt) const; - FString mid(uInt, uInt) const; + FString left (int) const; + FString left (uInt) const; + FString right (int) const; + FString right (uInt) const; + FString mid (int, int) const; + FString mid (uInt, uInt) const; std::vector split (const FString&); std::vector split (std::wstring&); diff --git a/src/fterm.cpp b/src/fterm.cpp index 652351fd..76a4ba62 100644 --- a/src/fterm.cpp +++ b/src/fterm.cpp @@ -2627,7 +2627,7 @@ void FTerm::updateVTerm (FTerm::term_area* area) // add the overlapping color to this character FOptiAttr::char_data ch, oc; memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); - oc = getOverlappedCharacter (gx+1, gy+1, area->widget); + oc = getOverlappedCharacter (gx+1 - ol, gy+1, area->widget); ch.fg_color = oc.fg_color; ch.bg_color = oc.bg_color; ch.reverse = false; @@ -2646,7 +2646,7 @@ void FTerm::updateVTerm (FTerm::term_area* area) { // restore one character on vterm FOptiAttr::char_data ch; - ch = getCoveredCharacter (gx+1, gy+1, area->widget); + ch = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); } else // not transparent @@ -2655,7 +2655,7 @@ void FTerm::updateVTerm (FTerm::term_area* area) { // get covered character + add the current color FOptiAttr::char_data ch; - ch = getCoveredCharacter (gx+1, gy+1, area->widget); + ch = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); ch.fg_color = ac->fg_color; ch.bg_color = ac->bg_color; ch.reverse = false; @@ -2675,7 +2675,7 @@ void FTerm::updateVTerm (FTerm::term_area* area) // add the covered background to this character FOptiAttr::char_data ch, cc; memcpy (&ch, ac, sizeof(FOptiAttr::char_data)); - cc = getCoveredCharacter (gx+1, gy+1, area->widget); + cc = getCoveredCharacter (gx+1 - ol, gy+1, area->widget); ch.bg_color = cc.bg_color; memcpy (tc, &ch, sizeof(FOptiAttr::char_data)); } @@ -2695,6 +2695,9 @@ void FTerm::updateVTerm (FTerm::term_area* area) if ( _xmin < short(vterm->changes[ay+y].xmin) ) vterm->changes[ay+y].xmin = uInt(_xmin); + if ( _xmax >= vterm->width ) + _xmax = vterm->width - 1; + if ( _xmax > short(vterm->changes[ay+y].xmax) ) vterm->changes[ay+y].xmax = uInt(_xmax); diff --git a/src/ftextview.cpp b/src/ftextview.cpp index 525d1d98..3d227d0a 100644 --- a/src/ftextview.cpp +++ b/src/ftextview.cpp @@ -1,6 +1,7 @@ // File: ftextview.cpp // Provides: class FTextView +#include "fdialog.h" #include "fstatusbar.h" #include "ftextview.h" @@ -65,13 +66,28 @@ void FTextView::init() //---------------------------------------------------------------------- void FTextView::draw() { + FWidget* parent = getParentWidget(); + bool is_text_dialog; updateVTerm(false); setColor(); if ( isMonochron() ) setReverse(true); - if ( ! isNewFont() ) + if ( parent + && parent->isDialogWidget() + && isPaddingIgnored() + && getGeometry() == FRect ( 1 + , 2 + , parent->getWidth() + , parent->getHeight()-1) ) + { + is_text_dialog = true; + } + else + is_text_dialog = false; + + if ( ! (is_text_dialog || isNewFont()) ) drawBorder(); if ( isMonochron() ) @@ -356,6 +372,9 @@ void FTextView::onKeyPress (FKeyEvent* ev) //---------------------------------------------------------------------- void FTextView::onMouseDown (FMouseEvent* ev) { + FWidget* parent; + FDialog* dialog; + if ( ev->getButton() != fc::LeftButton ) return; @@ -372,6 +391,73 @@ void FTextView::onMouseDown (FMouseEvent* ev) if ( statusBar() ) statusBar()->drawMessage(); } + + parent = getParentWidget(); + + if ( parent + && parent->isDialogWidget() + && (dialog = static_cast(parent)) != 0 + && dialog->isResizeable() + && ! dialog->isZoomed() ) + { + int b = ev->getButton(); + const FPoint& tp = ev->getTermPos(); + const FPoint& p = parent->termToWidgetPos(tp); + parent->setFocus(); + FMouseEvent* _ev = new FMouseEvent (fc::MouseDown_Event, p, tp, b); + FApplication::sendEvent (parent, _ev); + delete _ev; + } +} + +//---------------------------------------------------------------------- +void FTextView::onMouseUp (FMouseEvent* ev) +{ + FWidget* parent = getParentWidget(); + FDialog* dialog; + + if ( parent + && parent->isDialogWidget() + && (dialog = static_cast(parent)) != 0 + && dialog->isResizeable() + && ! dialog->isZoomed() ) + { + int b = ev->getButton(); + const FPoint& tp = ev->getTermPos(); + const FPoint& p = parent->termToWidgetPos(tp); + parent->setFocus(); + FMouseEvent* _ev = new FMouseEvent (fc::MouseUp_Event, p, tp, b); + FApplication::sendEvent (parent, _ev); + delete _ev; + } + + if ( vbar->isVisible() ) + vbar->redraw(); + + if ( hbar->isVisible() ) + hbar->redraw(); +} + +//---------------------------------------------------------------------- +void FTextView::onMouseMove (FMouseEvent* ev) +{ + FWidget* parent = getParentWidget(); + FDialog* dialog; + + if ( parent + && parent->isDialogWidget() + && (dialog = static_cast(parent)) != 0 + && dialog->isResizeable() + && ! dialog->isZoomed() ) + { + int b = ev->getButton(); + const FPoint& tp = ev->getTermPos(); + const FPoint& p = parent->termToWidgetPos(tp); + parent->setFocus(); + FMouseEvent* _ev = new FMouseEvent (fc::MouseMove_Event, p, tp, b); + FApplication::sendEvent (parent, _ev); + delete _ev; + } } //---------------------------------------------------------------------- @@ -456,7 +542,7 @@ void FTextView::cb_VBarChange (FWidget*, void*) int yoffset_before = yoffset; scrollType = vbar->getScrollType(); - switch ( scrollType ) + switch ( int(scrollType) ) { case FScrollbar::scrollPageBackward: distance = getHeight() + nf_offset - 2; diff --git a/src/ftextview.h b/src/ftextview.h index ae8de630..8be465e1 100644 --- a/src/ftextview.h +++ b/src/ftextview.h @@ -72,6 +72,8 @@ class FTextView : public FWidget void onKeyPress (FKeyEvent*); void onMouseDown (FMouseEvent*); + void onMouseUp (FMouseEvent*); + void onMouseMove (FMouseEvent*); void onWheel (FWheelEvent*); void onFocusIn (FFocusEvent*); void onFocusOut (FFocusEvent*); diff --git a/src/fwidget.cpp b/src/fwidget.cpp index 955144c8..a80ea366 100644 --- a/src/fwidget.cpp +++ b/src/fwidget.cpp @@ -186,7 +186,7 @@ void FWidget::setColorTheme() wc.selected_list_fg = fc::Cyan; wc.selected_list_bg = fc::White; wc.dialog_fg = fc::Black; - wc.dialog_resize_fg = fc::Red; + wc.dialog_resize_fg = fc::Cyan; wc.dialog_emphasis_fg = fc::Blue; wc.dialog_bg = fc::White; wc.error_box_fg = fc::White; @@ -878,6 +878,7 @@ FWidget* FWidget::getRootWidget() const obj = p_obj; p_obj = p_obj->getParentWidget(); } + return obj; } @@ -1694,10 +1695,8 @@ void FWidget::setSize (int width, int height, bool adjust) height = std::min (height, size_hints.max_height); height = std::max (height, size_hints.min_height); - if ( getWidth() == width && wsize.getWidth() == width ) - return; - - if ( getHeight() == height && wsize.getHeight() == height ) + if ( getWidth() == width && wsize.getWidth() == width + && getHeight() == height && wsize.getHeight() == height ) return; if ( width < 1 ) diff --git a/src/fwidget.h b/src/fwidget.h index c9f75a71..ebe5ab92 100644 --- a/src/fwidget.h +++ b/src/fwidget.h @@ -426,6 +426,7 @@ class FWidget : public FObject, public FTerm bool ignorePadding (bool); bool ignorePadding(); bool acceptPadding(); + bool isPaddingIgnored(); short getForegroundColor() const; short getBackgroundColor() const; @@ -459,9 +460,9 @@ class FWidget : public FObject, public FTerm void setY (int, bool = true); virtual void setPos (const FPoint&, bool = true); virtual void setPos (int, int, bool = true); - void setWidth (int, bool = true); - void setHeight (int, bool = true); - void setSize (int, int, bool = true); + virtual void setWidth (int, bool = true); + virtual void setHeight (int, bool = true); + virtual void setSize (int, int, bool = true); void setTopPadding (int, bool = true); void setLeftPadding (int, bool = true); void setBottomPadding (int, bool = true); @@ -702,6 +703,10 @@ inline bool FWidget::ignorePadding() inline bool FWidget::acceptPadding() { return ignore_padding = false; } +//---------------------------------------------------------------------- +inline bool FWidget::isPaddingIgnored() +{ return ignore_padding; } + //---------------------------------------------------------------------- inline void FWidget::setFocusable() { focusable = true; } diff --git a/src/fwindow.cpp b/src/fwindow.cpp index 9598060d..dbc3b9bd 100644 --- a/src/fwindow.cpp +++ b/src/fwindow.cpp @@ -130,6 +130,17 @@ void FWindow::setHeight (int h, bool adjust) resizeArea (vwin); } +//---------------------------------------------------------------------- +void FWindow::setSize (int w, int h, bool adjust) +{ + int old_width = getWidth(); + int old_height = getHeight(); + FWidget::setSize (w, h, adjust); + + if ( vwin && (getWidth() != old_width || getHeight() != old_height) ) + resizeArea (vwin); +} + //---------------------------------------------------------------------- void FWindow::setGeometry (int x, int y, int w, int h, bool adjust) { diff --git a/src/fwindow.h b/src/fwindow.h index 125efdd7..9aadab04 100644 --- a/src/fwindow.h +++ b/src/fwindow.h @@ -72,8 +72,9 @@ class FWindow : public FWidget const char* getClassName() const; virtual void show(); virtual void hide(); - void setWidth (int, bool = true); - void setHeight (int, bool = true); + virtual void setWidth (int, bool = true); + virtual void setHeight (int, bool = true); + virtual void setSize (int, int, bool = true); // make every setGeometry from FWidget available using FWidget::setGeometry; void setGeometry (int, int, int, int, bool = true); diff --git a/test/ui.cpp b/test/ui.cpp index 74e956f9..a04f8da6 100644 --- a/test/ui.cpp +++ b/test/ui.cpp @@ -187,6 +187,7 @@ TextWindow::TextWindow (FWidget* parent) scrollText = new FTextView(this); scrollText->ignorePadding(); scrollText->setGeometry (1, 2, getWidth(), getHeight()-1); + setMinimumSize (51, 6); scrollText->setFocus(); scrollText->insert(" -----------------------------------------------\n" " line 1\n" diff --git a/test/windows.cpp b/test/windows.cpp index 68b4b403..59da029f 100644 --- a/test/windows.cpp +++ b/test/windows.cpp @@ -20,12 +20,18 @@ class smallWindow : public FDialog { private: - FLabel* label; + FLabel* left_arrow; + FLabel* right_arrow; + FLabel* top_left_label; + FLabel* top_right_label; + FLabel* bottom_label; private: smallWindow (const smallWindow&); // Disabled copy constructor smallWindow& operator = (const smallWindow&); // and operator '=' void adjustSize(); + void onShow (FShowEvent*); + void onTimer (FTimerEvent*); public: explicit smallWindow (FWidget* = 0); // constructor @@ -38,25 +44,94 @@ class smallWindow : public FDialog //---------------------------------------------------------------------- smallWindow::smallWindow (FWidget* parent) : FDialog(parent) - , label() + , left_arrow() + , right_arrow() + , top_left_label() + , top_right_label() + , bottom_label() { - FString label_text = "resize \n" - "corner \u25E2"; - label = new FLabel (label_text, this); - label->setAlignment (fc::alignRight); - label->setForegroundColor (fc::DarkGray); - label->setGeometry (13, 4, 8, 2); + left_arrow = new FLabel ("\u25b2", this); + left_arrow->setForegroundColor (wc.label_inactive_fg); + left_arrow->setEmphasis(); + left_arrow->ignorePadding(); + left_arrow->setGeometry (2, 2, 1, 1); + + right_arrow = new FLabel ("\u25b2", this); + right_arrow->setForegroundColor (wc.label_inactive_fg); + right_arrow->setEmphasis(); + right_arrow->ignorePadding(); + right_arrow->setGeometry (getWidth() - 1, 2, 1, 1); + + FString top_left_label_text = "menu"; + top_left_label = new FLabel (top_left_label_text, this); + top_left_label->setForegroundColor (wc.label_inactive_fg); + top_left_label->setEmphasis(); + top_left_label->setGeometry (1, 1, 6, 1); + + FString top_right_label_text = "zoom"; + top_right_label = new FLabel (top_right_label_text, this); + top_right_label->setAlignment (fc::alignRight); + top_right_label->setForegroundColor (wc.label_inactive_fg); + top_right_label->setEmphasis(); + top_right_label->setGeometry (getClientWidth() - 5, 1, 6, 1); + + FString bottom_label_text = "resize\n" + "corner\n" + "\u25bc"; + bottom_label = new FLabel (bottom_label_text, this); + bottom_label->setAlignment (fc::alignRight); + bottom_label->setForegroundColor (wc.label_inactive_fg); + bottom_label->setEmphasis(); + bottom_label->setGeometry (13, 3, 6, 3); } //---------------------------------------------------------------------- smallWindow::~smallWindow() -{ } +{ + delOwnTimer(); +} //---------------------------------------------------------------------- void smallWindow::adjustSize() { + if ( isZoomed() ) + { + top_right_label->setText("unzoom"); + bottom_label->hide(); + } + else + { + top_right_label->setText("zoom"); + bottom_label->setVisible(); + } + FDialog::adjustSize(); - label->setGeometry (1, getClientHeight() - 1, getClientWidth(), 2); + right_arrow->setGeometry (getWidth() - 1, 2, 1, 1); + top_right_label->setGeometry (getClientWidth() - 5, 1, 6, 1); + bottom_label->setGeometry (1, getClientHeight() - 2, getClientWidth(), 3); +} + +//---------------------------------------------------------------------- +void smallWindow::onShow (FShowEvent*) +{ + addTimer(1000); +} + +//---------------------------------------------------------------------- +void smallWindow::onTimer (FTimerEvent*) +{ + left_arrow->unsetEmphasis(); + left_arrow->redraw(); + right_arrow->unsetEmphasis(); + right_arrow->redraw(); + top_left_label->unsetEmphasis(); + top_left_label->redraw(); + top_right_label->unsetEmphasis(); + top_right_label->redraw(); + bottom_label->unsetEmphasis(); + bottom_label->redraw(); + updateTerminal(); + delOwnTimer(); } @@ -72,7 +147,7 @@ class Window : public FDialog private: typedef struct { - bool is_open; + bool is_open; FString* title; FDialog* dgl; } @@ -433,7 +508,7 @@ void Window::adjustSize() if ( Y < 2) Y = 2; - setPos (X, Y, false); + move (X, Y); iter = begin = windows.begin(); while ( iter != windows.end() ) @@ -444,7 +519,7 @@ void Window::adjustSize() n = int(std::distance(begin, iter)); x = dx + 5 + (n%3)*25 + int(n/3)*3; y = dy + 11 + int(n/3)*3; - (*iter)->dgl->setPos (x, y, false); + (*iter)->dgl->move (x, y); } ++iter;