diff options
| -rw-r--r-- | FL/Fl_Help_View.H | 103 | ||||
| -rw-r--r-- | src/Fl_Help_View.cxx | 177 |
2 files changed, 156 insertions, 124 deletions
diff --git a/FL/Fl_Help_View.H b/FL/Fl_Help_View.H index de0e0748b..e529253f6 100644 --- a/FL/Fl_Help_View.H +++ b/FL/Fl_Help_View.H @@ -166,55 +166,68 @@ private: // classes, structs, and types void pop(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c); size_t count() const; protected: - std::vector<Font_Style> elts_; ///< font elements + std::vector<Font_Style> elts_; ///< font elements }; - enum class Align { RIGHT = -1, CENTER, LEFT }; ///< Alignments + enum class Align { RIGHT = -1, CENTER, LEFT }; ///< Alignments + enum class Mode { DRAW, PUSH, DRAG }; ///< Draw modes + private: // data members - std::string title_; ///< Title string - Fl_Color defcolor_, ///< Default text color - bgcolor_, ///< Background color - textcolor_, ///< Text color - linkcolor_; ///< Link color - Fl_Font textfont_; ///< Default font for text - Fl_Fontsize textsize_; ///< Default font size - const char *value_; ///< HTML text value - Font_Stack fstack_; ///< font stack management - std::vector<Text_Block> blocks_; ///< Blocks - - Fl_Help_Func *link_; ///< Link transform function - - std::vector<std::shared_ptr<Link>> link_list_; ///< List of links for each line - - std::map<std::string, int> target_line_map_; ///< Map of targets for fast access - - std::string directory_; ///< Directory for current file - std::string filename_; ///< Current filename - - int topline_, ///< Top line in document, measure in pixels - leftline_, ///< Lefthand position in pixels - size_, ///< Total document height in pixels - hsize_, ///< Maximum document width - scrollbar_size_; ///< Size for both scrollbars - Fl_Scrollbar scrollbar_, ///< Vertical scrollbar for document - hscrollbar_; ///< Horizontal scrollbar - - static int selection_first_; - static int selection_last_; - static int selection_push_first_; - static int selection_push_last_; - static int selection_drag_first_; - static int selection_drag_last_; - static int selected_; - static int draw_mode_; // 0 if drawing, 1 if mouse down, 2 if mouse dragged - static int mouse_x_; - static int mouse_y_; - static int current_pos_; - static Fl_Help_View *current_view_; - static Fl_Color hv_selection_color_; - static Fl_Color hv_selection_text_color_; + // HTML source and raw data + + const char *value_; ///< Copy of raw HTML text, as set by `value()` or `load()` + std::string directory_; ///< Directory for current document + std::string filename_; ///< Original file name from `load()` + + // HTML document data + + std::string title_; ///< Title string from <title> tag + Font_Stack fstack_; ///< Font and style stack + std::vector<Text_Block> blocks_; ///< List of all text blocks on screen + std::vector<std::shared_ptr<Link>> link_list_; ///< List of all clickable links and their position on screen + std::map<std::string, int> target_line_map_; ///< List of vertical position of all HTML Targets in a document + + int topline_; ///< Vertical offset of document, measure in pixels + int leftline_; ///< Horizontal offset of document, measure in pixels + int size_; ///< Total document height in pixels + int hsize_; ///< Maximum document width in pixels + + // Default visual attributes + + Fl_Color defcolor_; ///< Default text color, defaults to FL_FOREGROUND_COLOR + Fl_Color bgcolor_; ///< Background color, defaults to FL_BACKGROUND_COLOR + Fl_Color textcolor_; ///< Text color, defaults to FL_FOREGROUND_COLOR + Fl_Color linkcolor_; ///< Link color, FL_SELECTION_COLOR + Fl_Font textfont_; ///< Default font for text, FL_TIMES + Fl_Fontsize textsize_; ///< Default font size, defaults to 12, should be FL_NORMAL_SIZE + + // Text selection and mouse handling + + Mode selection_mode_; ///< Remember election mode between FL_PUSH, FL_DRAG, and FL_RELEASE + bool selected_; ///< True if there is text selected + int selection_first_; ///< First character of selection, offset in value_ + int selection_last_; ///< Last character of selection, offset in value_ + Fl_Color tmp_selection_color_; ///< Selection color during draw operation + Fl_Color selection_text_color_; ///< Selection text color during draw operation + // The following members are static because we need them only once during mouse events + static int selection_push_first_; ///< First character of selection during mouse down + static int selection_push_last_; ///< Last character of selection during mouse down + static int selection_drag_first_; ///< First character of selection during mouse drag + static int selection_drag_last_; ///< Last character of selection during mouse drag + static Mode draw_mode_; ///< Temporarily modify `draw()` method to measure selection start or end during `handle()` + static int current_pos_; ///< Temporarily store text offset while measuring during `handle()` + + // Callback + + Fl_Help_Func *link_; ///< Link transform function + + // Scrollbars + + Fl_Scrollbar scrollbar_; ///< Vertical scrollbar for document + Fl_Scrollbar hscrollbar_; ///< Horizontal scrollbar + int scrollbar_size_; ///< Size for both scrollbars private: // methods @@ -239,7 +252,7 @@ private: // methods void hv_draw(const char *t, int x, int y, int entity_extra_length = 0); char begin_selection(); char extend_selection(); - void end_selection(int c=0); + void end_selection(); void clear_global_selection(); std::shared_ptr<Link> find_link(int, int); void follow_link(std::shared_ptr<Link>); diff --git a/src/Fl_Help_View.cxx b/src/Fl_Help_View.cxx index a67973be1..283e92f09 100644 --- a/src/Fl_Help_View.cxx +++ b/src/Fl_Help_View.cxx @@ -340,20 +340,12 @@ size_t Fl_Help_View::Font_Stack::count() const { // We don't put the offscreen buffer in the help view class because // we'd need to include platform.H in the header... static Fl_Offscreen fl_help_view_buffer; -int Fl_Help_View::selection_first_ = 0; -int Fl_Help_View::selection_last_ = 0; int Fl_Help_View::selection_push_first_ = 0; int Fl_Help_View::selection_push_last_ = 0; int Fl_Help_View::selection_drag_first_ = 0; int Fl_Help_View::selection_drag_last_ = 0; -int Fl_Help_View::selected_ = 0; -int Fl_Help_View::draw_mode_ = 0; -int Fl_Help_View::mouse_x_ = 0; -int Fl_Help_View::mouse_y_ = 0; +Fl_Help_View::Mode Fl_Help_View::draw_mode_ = Mode::DRAW; int Fl_Help_View::current_pos_ = 0; -Fl_Help_View *Fl_Help_View::current_view_ = 0L; -Fl_Color Fl_Help_View::hv_selection_color_; -Fl_Color Fl_Help_View::hv_selection_text_color_; /** @@ -369,34 +361,32 @@ Fl_Color Fl_Help_View::hv_selection_text_color_; */ void Fl_Help_View::hv_draw(const char *t, int x, int y, int entity_extra_length) { - if (draw_mode_ == 0) { - if (selected_ && current_view_==this && current_pos_<selection_last_ && current_pos_>=selection_first_) { + if (draw_mode_ == Mode::DRAW) { + if (selected_ && current_pos_<selection_last_ && current_pos_>=selection_first_) { Fl_Color c = fl_color(); - fl_color(hv_selection_color_); + fl_color(tmp_selection_color_); int w = (int)fl_width(t); if (current_pos_+(int)strlen(t)<selection_last_) w += (int)fl_width(' '); fl_rectf(x, y+fl_descent()-fl_height(), w, fl_height()); - fl_color(hv_selection_text_color_); + fl_color(selection_text_color_); fl_draw(t, x, y); fl_color(c); } else { fl_draw(t, x, y); } } else { - // If draw_mode_ is set, we don;t actually draw anything, but measure where - // text blocks are on screen during a selection process with the mouse. - // draw_mode_ is 1 if the mouse button is first pressed down, and 2 while - // the mouse is dragged. + // If draw_mode_ is not DRAW, we don't actually draw anything, but instead + // measure where text blocks are on screen during a mouse selection process. int w = (int)fl_width(t); - if (mouse_x_>=x && mouse_x_<x+w) { - if (mouse_y_>=y-fl_height()+fl_descent()&&mouse_y_<=y+fl_descent()) { + if ( (Fl::event_x() >= x) && (Fl::event_x() < x+w) ) { + if ( (Fl::event_y() >= y-fl_height()+fl_descent()) && (Fl::event_y() <= y+fl_descent()) ) { int f = (int) current_pos_; int l = (int) (f+strlen(t)); // use 'quote_char' to calculate the true length of the HTML string - if (draw_mode_==1) { + if (draw_mode_ == Mode::PUSH) { selection_push_first_ = f; selection_push_last_ = l; - } else { + } else { // Mode::DRAG selection_drag_first_ = f; selection_drag_last_ = l + entity_extra_length; } @@ -591,9 +581,15 @@ void Fl_Help_View::draw() if (!value_) return; - if (current_view_ == this && selected_) { - hv_selection_color_ = FL_SELECTION_COLOR; - hv_selection_text_color_ = fl_contrast(textcolor_, FL_SELECTION_COLOR); + if (selected_) { + if (Fl::focus() == this) { + // If this widget has the focus, we use the selection color directly + tmp_selection_color_ = selection_color(); + } else { + // Otherwise we blend the selection color with the background color + tmp_selection_color_ = fl_color_average(bgcolor_, selection_color(), 0.8f); + } + selection_text_color_ = fl_contrast(textcolor_, tmp_selection_color_); } current_pos_ = 0; @@ -2931,8 +2927,10 @@ void Fl_Help_View::follow_link(std::shared_ptr<Link> linkp) */ void Fl_Help_View::clear_selection() { - if (current_view_==this) - clear_global_selection(); + selected_ = false; + selection_first_ = 0; + selection_last_ = 0; + redraw(); } @@ -2943,9 +2941,8 @@ void Fl_Help_View::select_all() { clear_global_selection(); if (!value_) return; - current_view_ = this; selection_drag_last_ = selection_last_ = (int) strlen(value_); - selected_ = 1; + selected_ = true; } @@ -2955,7 +2952,7 @@ void Fl_Help_View::clear_global_selection() selection_push_first_ = selection_push_last_ = 0; selection_drag_first_ = selection_drag_last_ = 0; selection_first_ = selection_last_ = 0; - selected_ = 0; + selected_ = false; } @@ -2965,16 +2962,13 @@ char Fl_Help_View::begin_selection() if (!fl_help_view_buffer) fl_help_view_buffer = fl_create_offscreen(1, 1); - mouse_x_ = Fl::event_x(); - mouse_y_ = Fl::event_y(); - draw_mode_ = 1; + draw_mode_ = Mode::PUSH; - current_view_ = this; fl_begin_offscreen(fl_help_view_buffer); draw(); fl_end_offscreen(); - draw_mode_ = 0; + draw_mode_ = Mode::DRAW; if (selection_push_last_) return 1; else return 0; @@ -2997,16 +2991,15 @@ char Fl_Help_View::extend_selection() int sf = selection_first_, sl = selection_last_; - selected_ = 1; - mouse_x_ = Fl::event_x(); - mouse_y_ = Fl::event_y(); - draw_mode_ = 2; + selected_ = true; + + draw_mode_ = Mode::DRAG; fl_begin_offscreen(fl_help_view_buffer); draw(); fl_end_offscreen(); - draw_mode_ = 0; + draw_mode_ = Mode::DRAW; if (selection_push_first_ < selection_drag_first_) { selection_first_ = selection_push_first_; @@ -3057,10 +3050,33 @@ static constexpr uint32_t CMD(char a, char b, char c, char d) } -void Fl_Help_View::end_selection(int clipboard) +void Fl_Help_View::end_selection() { - if (!selected_ || current_view_!=this) - return; + selection_push_first_ = 0; + selection_push_last_ = 0; + selection_drag_first_ = 0; + selection_drag_last_ = 0; +} + + +/** + \brief Check if the user selected text in this view. + \return 1 if text is selected, 0 if no text is selected + */ +int Fl_Help_View::text_selected() { + return selected_; +} + + +/** + \brief If text is selected in this view, copy it to a clipboard. + \param[in] clipboard for x11 only, 0=selection buffer, 1=clipboard, 2=both + \return 1 if text is selected, 0 if no text is selected + */ +int Fl_Help_View::copy(int clipboard) { + if (!selected_) + return 0; + // convert the select part of our html text into some kind of somewhat readable UTF-8 // and store it in the selection buffer int p = 0; @@ -3144,33 +3160,7 @@ void Fl_Help_View::end_selection(int clipboard) Fl::copy(txt, (int) strlen(txt), clipboard); // printf("copy [%s]\n", txt); free(txt); -} - - -/** - \brief Check if the user selected text in this view. - \return 1 if text is selected, 0 if no text is selected - */ -int Fl_Help_View::text_selected() { - if (current_view_==this) - return selected_; - else - return 0; -} - - -/** - \brief If text is selected in this view, copy it to a clipboard. - \param[in] clipboard for x11 only, 0=selection buffer, 1=clipboard, 2=both - \return 1 if text is selected, 0 if no text is selected - */ -int Fl_Help_View::copy(int clipboard) { - if (text_selected()) { - end_selection(clipboard); - return 1; - } else { - return 0; - } + return 1; } @@ -3189,11 +3179,14 @@ int Fl_Help_View::handle(int event) switch (event) { case FL_FOCUS: - redraw(); + // Selection style changes, so ask for a redraw + if (selected_) + redraw(); return 1; case FL_UNFOCUS: - clear_selection(); - redraw(); + // Selection style changes, so ask for a redraw + if (selected_) + redraw(); return 1; case FL_ENTER : Fl_Group::handle(event); @@ -3206,6 +3199,7 @@ int Fl_Help_View::handle(int event) else fl_cursor(FL_CURSOR_DEFAULT); return 1; case FL_PUSH: + // RMB will pop up a menu if (Fl::event_button() == FL_RIGHT_MOUSE) { rmb_menu[0].label(copy_menu_text); if (text_selected()) @@ -3219,36 +3213,52 @@ int Fl_Help_View::handle(int event) copy(); break; } + return 1; } - if (Fl_Group::handle(event)) return 1; + // Check if the scrollbars used up the event + if (Fl_Group::handle(event)) + return 1; + // Check if the user clicked on a link linkp = find_link(xx, yy); if (linkp) { fl_cursor(FL_CURSOR_HAND); return 1; } + // If nothing else, the user cancels the current selection and might start a new one if (begin_selection()) { + selection_mode_ = Mode::PUSH; fl_cursor(FL_CURSOR_INSERT); return 1; } + // Nothing to do. fl_cursor(FL_CURSOR_DEFAULT); return 1; case FL_DRAG: + // If we clicked on a link, check if this remains a click, or if the user drags the mouse if (linkp) { if (Fl::event_is_click()) { fl_cursor(FL_CURSOR_HAND); } else { - fl_cursor(FL_CURSOR_DEFAULT); // should be "FL_CURSOR_CANCEL" if we had it + // No longer just a click, so we cancel the link and start a drag selection + linkp = 0; + if (begin_selection()) { + selection_mode_ = Mode::PUSH; + fl_cursor(FL_CURSOR_INSERT); + } } - return 1; } - if (current_view_==this && selection_push_last_) { - if (extend_selection()) redraw(); + // If the FL_PUSH started a selection, we extend the selection + if (selection_mode_ == Mode::PUSH) { + if (extend_selection()) + redraw(); fl_cursor(FL_CURSOR_INSERT); return 1; } + // Nothing to do. fl_cursor(FL_CURSOR_DEFAULT); return 1; case FL_RELEASE: + // If we clicked on a link, follow it if (linkp) { if (Fl::event_is_click()) { follow_link(linkp); @@ -3257,10 +3267,13 @@ int Fl_Help_View::handle(int event) linkp = 0; return 1; } - if (current_view_==this && selection_push_last_) { + // If in a selection process, end the selection. + if (selection_mode_ == Mode::PUSH) { end_selection(); + selection_mode_ = Mode::DRAW; return 1; } + // Nothing to do. return 1; case FL_SHORTCUT: { int mods = Fl::event_state() & (FL_META|FL_CTRL|FL_ALT|FL_SHIFT); @@ -3268,7 +3281,7 @@ int Fl_Help_View::handle(int event) switch ( Fl::event_key() ) { case 'a': select_all(); redraw(); return 1; case 'c': - case 'x': end_selection(1); return 1; + case 'x': copy(1); return 1; } } break; } @@ -3311,6 +3324,12 @@ Fl_Help_View::Fl_Help_View(int xx, int yy, int ww, int hh, const char *l) leftline_ = 0; size_ = 0; hsize_ = 0; + + selection_mode_ = Mode::DRAW; + selected_ = false; + selection_first_ = 0; + selection_last_ = 0; + scrollbar_size_ = 0; scrollbar_.value(0, hh, 0, 1); |
