Skip to content

Commit

Permalink
Implementation of the mouse selection in the FTextView. Can be activa…
Browse files Browse the repository at this point in the history
…ted by setSelectable()
  • Loading branch information
gansm committed Apr 2, 2024
1 parent 8d547c2 commit 580c499
Show file tree
Hide file tree
Showing 8 changed files with 605 additions and 101 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2023-04-02 Markus Gans <guru.mail@muenster.de>
* Implementation of the mouse selection in the FTextView. Can be
activated by setSelectable()

2023-03-26 Markus Gans <guru.mail@muenster.de>
* Visual highlighting of the selected text in FTextView

Expand Down
7 changes: 4 additions & 3 deletions final/dialog/fdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,9 @@ void FDialog::onKeyPress (FKeyEvent* ev)
if ( titlebar.buttons && isDialogMenuKey(key) )
{
ev->accept();
// open the titlebar menu
// Open the titlebar menu
openMenu();
// focus to the first enabled item
// Focus to the first enabled item
selectFirstMenuItem();
}

Expand Down Expand Up @@ -1427,7 +1427,8 @@ inline void FDialog::leaveMinimizeButton (const MouseStates& ms)
//----------------------------------------------------------------------
void FDialog::pressMinimizeButton (const MouseStates& ms)
{
if ( ! isMouseOverMinimizeButton(ms) || ! titlebar.minimize_button_pressed )
if ( ! isMouseOverMinimizeButton(ms)
|| ! titlebar.minimize_button_pressed )
return;

// Zoom to maximum or restore the window size
Expand Down
96 changes: 69 additions & 27 deletions final/fapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ FWidget* FWidget::active_window {nullptr}; // the active window
FWidget* FWidget::focus_widget {nullptr}; // has keyboard input focus
FWidget* FWidget::clicked_widget {nullptr}; // is focused by click
FWidget* FApplication::clicked_widget {nullptr}; // is focused by click
FWidget* FApplication::wheel_widget {nullptr}; // is focused on wheel
FWidget* FWidget::open_menu {nullptr}; // currently open menu
FWidget* FWidget::move_resize_widget {nullptr}; // move or resize by keyboard
FWidget* FApplication::keyboard_widget {nullptr}; // has the keyboard focus
Expand Down Expand Up @@ -450,6 +451,7 @@ void FApplication::init()

// Restister mouse handler callbacks
registerMouseHandler (FApplication::determineClickedWidget);
registerMouseHandler (FApplication::determineWheelWidget);
registerMouseHandler (FApplication::unsetMoveResizeMode);

// Initialize logging
Expand Down Expand Up @@ -776,6 +778,7 @@ void FApplication::mouseEvent (const FMouseData& md) const
mouse_handler(md); // Execute mouse handler

sendMouseEvent (md);
sendMouseWheelEvent (md);
}

//----------------------------------------------------------------------
Expand Down Expand Up @@ -1006,6 +1009,9 @@ void FApplication::processTerminalFocus (const FKey& key)
//----------------------------------------------------------------------
void FApplication::determineClickedWidget (const FMouseData& md)
{
if ( isWheelEvent(md) )
return;

clicked_widget = FWidget::getClickedWidget();

// Check if the clicked widget has already been found
Expand All @@ -1027,6 +1033,25 @@ void FApplication::determineClickedWidget (const FMouseData& md)
setClickedWidget (clicked_widget);
}

//----------------------------------------------------------------------
void FApplication::determineWheelWidget (const FMouseData& md)
{
if ( ! isWheelEvent(md) )
return;

const auto& mouse_position = md.getPos();

// Determine the window object on the current click position
auto window = FWindow::getWindowWidgetAt (mouse_position);

if ( ! window )
return;

// Determine the widget at the current click position
auto child = window->childWidgetAt(mouse_position);
wheel_widget = ( child != nullptr ) ? child : window;
}

//----------------------------------------------------------------------
auto FApplication::isNonActivatingMouseEvent (const FMouseData& md) -> bool
{
Expand All @@ -1039,6 +1064,15 @@ auto FApplication::isNonActivatingMouseEvent (const FMouseData& md) -> bool
|| md.isMoved();
}

//----------------------------------------------------------------------
auto FApplication::isWheelEvent (const FMouseData& md) -> bool
{
return md.isWheelUp()
|| md.isWheelDown()
|| md.isWheelLeft()
|| md.isWheelRight();
};

//----------------------------------------------------------------------
void FApplication::unsetMoveResizeMode (const FMouseData&)
{
Expand All @@ -1057,7 +1091,7 @@ void FApplication::unsetMoveResizeMode (const FMouseData&)
//----------------------------------------------------------------------
void FApplication::sendMouseEvent (const FMouseData& md) const
{
if ( ! FWidget::getClickedWidget() ) // No widget was clicked
if ( ! FWidget::getClickedWidget() || wheel_widget ) // No widget was clicked
return;

const auto& mouse_position = md.getPos();
Expand All @@ -1072,32 +1106,41 @@ void FApplication::sendMouseEvent (const FMouseData& md) const
if ( md.isMetaKeyPressed() )
key_state |= MouseButton::Meta;

const auto& widgetMousePos = clicked_widget->termToWidgetPos(mouse_position);
const auto& widget_mouse_pos = clicked_widget->termToWidgetPos(mouse_position);

if ( md.isMoved() )
{
sendMouseMoveEvent (md, widgetMousePos, mouse_position, key_state);
sendMouseMoveEvent (md, widget_mouse_pos, mouse_position, key_state);
}
else
{
sendMouseLeftClickEvent (md, widgetMousePos, mouse_position, key_state);
sendMouseRightClickEvent (md, widgetMousePos, mouse_position, key_state);
sendMouseMiddleClickEvent (md, widgetMousePos, mouse_position, key_state);
sendMouseLeftClickEvent (md, widget_mouse_pos, mouse_position, key_state);
sendMouseRightClickEvent (md, widget_mouse_pos, mouse_position, key_state);
sendMouseMiddleClickEvent (md, widget_mouse_pos, mouse_position, key_state);
}
}

sendWheelEvent (md, widgetMousePos, mouse_position);
//----------------------------------------------------------------------
void FApplication::sendMouseWheelEvent (const FMouseData& md)const
{
if ( ! wheel_widget ) // No widget under the mouse pointer
return;

const auto& mouse_position = md.getPos();
const auto& widget_mouse_pos = wheel_widget->termToWidgetPos(mouse_position);
sendWheelEvent (md, widget_mouse_pos, mouse_position);
}

//----------------------------------------------------------------------
void FApplication::sendMouseMoveEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& widget_mouse_pos
, const FPoint& mouse_position
, MouseButton key_state ) const
{
if ( md.isLeftButtonPressed() )
{
FMouseEvent m_down_ev ( Event::MouseMove
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Left | key_state );
sendEvent (clicked_widget, &m_down_ev);
Expand All @@ -1106,7 +1149,7 @@ void FApplication::sendMouseMoveEvent ( const FMouseData& md
if ( md.isRightButtonPressed() )
{
FMouseEvent m_down_ev ( Event::MouseMove
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Right | key_state );
sendEvent (clicked_widget, &m_down_ev);
Expand All @@ -1115,7 +1158,7 @@ void FApplication::sendMouseMoveEvent ( const FMouseData& md
if ( md.isMiddleButtonPressed() )
{
FMouseEvent m_down_ev ( Event::MouseMove
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Middle | key_state );
sendEvent (clicked_widget, &m_down_ev);
Expand All @@ -1124,30 +1167,30 @@ void FApplication::sendMouseMoveEvent ( const FMouseData& md

//----------------------------------------------------------------------
void FApplication::sendMouseLeftClickEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& widget_mouse_pos
, const FPoint& mouse_position
, MouseButton key_state ) const
{
if ( md.isLeftButtonDoubleClick() )
{
FMouseEvent m_dblclick_ev ( Event::MouseDoubleClick
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Left | key_state );
sendEvent (clicked_widget, &m_dblclick_ev);
}
else if ( md.isLeftButtonPressed() )
{
FMouseEvent m_down_ev ( Event::MouseDown
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Left | key_state );
sendEvent (clicked_widget, &m_down_ev);
}
else if ( md.isLeftButtonReleased() )
{
FMouseEvent m_up_ev ( Event::MouseUp
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Left | key_state );
auto released_widget = clicked_widget;
Expand All @@ -1162,22 +1205,22 @@ void FApplication::sendMouseLeftClickEvent ( const FMouseData& md

//----------------------------------------------------------------------
void FApplication::sendMouseRightClickEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& widget_mouse_pos
, const FPoint& mouse_position
, MouseButton key_state ) const
{
if ( md.isRightButtonPressed() )
{
FMouseEvent m_down_ev ( Event::MouseDown
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Right | key_state );
sendEvent (clicked_widget, &m_down_ev);
}
else if ( md.isRightButtonReleased() )
{
FMouseEvent m_up_ev ( Event::MouseUp
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Right | key_state );
auto released_widget = clicked_widget;
Expand All @@ -1192,22 +1235,22 @@ void FApplication::sendMouseRightClickEvent ( const FMouseData& md

//----------------------------------------------------------------------
void FApplication::sendMouseMiddleClickEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& widget_mouse_pos
, const FPoint& mouse_position
, MouseButton key_state ) const
{
if ( md.isMiddleButtonPressed() )
{
FMouseEvent m_down_ev ( Event::MouseDown
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Middle | key_state );
sendEvent (clicked_widget, &m_down_ev);
}
else if ( md.isMiddleButtonReleased() )
{
FMouseEvent m_up_ev ( Event::MouseUp
, widgetMousePos
, widget_mouse_pos
, mouse_position
, MouseButton::Middle | key_state );
auto released_widget = clicked_widget;
Expand All @@ -1224,11 +1267,10 @@ void FApplication::sendMouseMiddleClickEvent ( const FMouseData& md

//----------------------------------------------------------------------
void FApplication::sendWheelEvent ( const FMouseData& md
, const FPoint& widgetMousePos
, const FPoint& widget_mouse_pos
, const FPoint& mouse_position ) const
{
if ( ! md.isWheelUp() && ! md.isWheelDown()
&& ! md.isWheelLeft() && ! md.isWheelRight() )
if ( ! isWheelEvent(md) )
return;

auto mouse_wheel = [&md] ()
Expand All @@ -1249,12 +1291,12 @@ void FApplication::sendWheelEvent ( const FMouseData& md
}();

FWheelEvent wheel_ev ( Event::MouseWheel
, widgetMousePos
, widget_mouse_pos
, mouse_position
, mouse_wheel );
auto scroll_over_widget = clicked_widget;
setClickedWidget(nullptr);
auto scroll_over_widget = wheel_widget;
sendEvent (scroll_over_widget, &wheel_ev);
wheel_widget = nullptr;
}

//----------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions final/fapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,12 @@ class FApplication : public FWidget
auto processAccelerator (const FWidget&) const -> bool;
void processTerminalFocus (const FKey&);
static void determineClickedWidget (const FMouseData&);
static void determineWheelWidget (const FMouseData&);
static auto isNonActivatingMouseEvent (const FMouseData&) -> bool;
static auto isWheelEvent (const FMouseData&) -> bool;
static void unsetMoveResizeMode (const FMouseData&);
void sendMouseEvent (const FMouseData&) const;
void sendMouseWheelEvent (const FMouseData&) const;
void sendMouseMoveEvent ( const FMouseData&
, const FPoint&
, const FPoint&
Expand Down Expand Up @@ -248,6 +251,7 @@ class FApplication : public FWidget
static int quit_code;
static bool quit_now;
static FWidget* clicked_widget;
static FWidget* wheel_widget;
static FWidget* keyboard_widget;
};

Expand Down
2 changes: 1 addition & 1 deletion final/widget/flineedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ void FLineEdit::setCursorPositionByMouseClick (const FMouseEvent* ev)
//----------------------------------------------------------------------
void FLineEdit::handleAutoScroll (const FMouseEvent* ev)
{
// auto-scrolling when dragging mouse outside the widget
// Auto-scrolling when dragging mouse outside the widget

const int mouse_x = ev->getX();

Expand Down
12 changes: 6 additions & 6 deletions final/widget/flistbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,10 +847,10 @@ inline void FListBox::setCurrentLineAttributes ( int y
, bool line_has_brackets
, bool& search_mark )
{
const auto& flags = getFlags();
const auto& widget_flags = getFlags();
const auto& output = FVTerm::getFOutput();

if ( flags.focus.focus && output->getMaxColor() < 16 )
if ( widget_flags.focus.focus && output->getMaxColor() < 16 )
setBold();

if ( is_line_selected )
Expand All @@ -866,13 +866,13 @@ inline void FListBox::setCurrentLineAttributes ( int y
inline void FListBox::setSelectedCurrentLineAttributes (int y)
{
const auto& wc = getColorTheme();
const auto& flags = getFlags();
const auto& widget_flags = getFlags();
const auto& output = FVTerm::getFOutput();
const auto& current_element = wc->current_element;

if ( output->isMonochron() )
setBold();
else if ( flags.focus.focus )
else if ( widget_flags.focus.focus )
setColor ( current_element.selected_focus_fg
, current_element.selected_focus_bg );
else
Expand All @@ -888,7 +888,7 @@ inline void FListBox::setUnselectedCurrentLineAttributes ( int y
, bool& search_mark )
{
const auto& wc = getColorTheme();
const auto& flags = getFlags();
const auto& widget_flags = getFlags();
const auto& output = FVTerm::getFOutput();
const std::size_t inc_len = data.inc_search.getLength();
const std::size_t inc_width = getColumnWidth(data.inc_search);
Expand All @@ -897,7 +897,7 @@ inline void FListBox::setUnselectedCurrentLineAttributes ( int y
if ( output->isMonochron() )
unsetBold();

if ( ! flags.focus.focus )
if ( ! widget_flags.focus.focus )
{
setColor ( current_element.fg
, current_element.bg );
Expand Down
Loading

0 comments on commit 580c499

Please sign in to comment.