mirror of https://github.com/fltk/fltk
Add RMB pulldown menu to Fl_Help_View, #75
- append underscores to private varaibles per CMP - add public Fl_Help_View::copy() and Fl_Help_View::text_selected() - add public Fl_Help_View::copy_menu_text - fixes some of the focus handling - add pulldown menu to copy selected text
This commit is contained in:
parent
e7b8a24685
commit
089f31018b
|
@ -235,20 +235,20 @@ class FL_EXPORT Fl_Help_View : public Fl_Group { // Help viewer widget
|
|||
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;
|
||||
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;
|
||||
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_;
|
||||
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_;
|
||||
|
||||
|
||||
void initfont(Fl_Font &f, Fl_Fontsize &s, Fl_Color &c) { f = textfont_; s = textsize_; c = textcolor_; fstack_.init(f, s, c); }
|
||||
|
@ -286,6 +286,8 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
static const char *copy_menu_text;
|
||||
|
||||
Fl_Help_View(int xx, int yy, int ww, int hh, const char *l = 0);
|
||||
~Fl_Help_View();
|
||||
/** Returns the current directory for the text in the buffer. */
|
||||
|
@ -383,6 +385,12 @@ public:
|
|||
void scrollbar_size(int newSize) {
|
||||
scrollbar_size_ = newSize;
|
||||
}
|
||||
|
||||
// Check if the user selected text in this view.
|
||||
int text_selected();
|
||||
|
||||
// If text is selected in this view, copy it to a clipboard.
|
||||
int copy(int clipboard=1);
|
||||
};
|
||||
|
||||
#endif // !Fl_Help_View_H
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Pixmap.H>
|
||||
#include <FL/Fl_Menu_Item.H>
|
||||
#include "Fl_Int_Vector.H"
|
||||
#include "Fl_String.H"
|
||||
|
||||
|
@ -130,6 +131,14 @@ static const char * const broken_xpm[] =
|
|||
|
||||
static Fl_Pixmap broken_image(broken_xpm);
|
||||
|
||||
/** [this text may be customized at run-time] */
|
||||
const char *Fl_Help_View::copy_menu_text = "Copy";
|
||||
|
||||
static Fl_Menu_Item rmb_menu[] = {
|
||||
{ NULL, 0, NULL, (void*)1 }, // Copy
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
//
|
||||
// Simple margin stack for Fl_Help_View::format()...
|
||||
//
|
||||
|
@ -210,51 +219,51 @@ img->draw()
|
|||
// 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;
|
||||
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;
|
||||
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;
|
||||
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_;
|
||||
|
||||
/*
|
||||
* This function must be optimized for speed!
|
||||
*/
|
||||
void Fl_Help_View::hv_draw(const char *t, int x, int y, int entity_extra_length)
|
||||
{
|
||||
if (selected && current_view==this && current_pos<selection_last && current_pos>=selection_first) {
|
||||
if (selected_ && current_view_==this && current_pos_<selection_last_ && current_pos_>=selection_first_) {
|
||||
Fl_Color c = fl_color();
|
||||
fl_color(hv_selection_color);
|
||||
fl_color(hv_selection_color_);
|
||||
int w = (int)fl_width(t);
|
||||
if (current_pos+(int)strlen(t)<selection_last)
|
||||
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(hv_selection_text_color_);
|
||||
fl_draw(t, x, y);
|
||||
fl_color(c);
|
||||
} else {
|
||||
fl_draw(t, x, y);
|
||||
}
|
||||
if (draw_mode) {
|
||||
if (draw_mode_) {
|
||||
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()) {
|
||||
int f = (int) current_pos;
|
||||
if (mouse_x_>=x && mouse_x_<x+w) {
|
||||
if (mouse_y_>=y-fl_height()+fl_descent()&&mouse_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) {
|
||||
selection_push_first = f;
|
||||
selection_push_last = l;
|
||||
if (draw_mode_==1) {
|
||||
selection_push_first_ = f;
|
||||
selection_push_last_ = l;
|
||||
} else {
|
||||
selection_drag_first = f;
|
||||
selection_drag_last = l + entity_extra_length;
|
||||
selection_drag_first_ = f;
|
||||
selection_drag_last_ = l + entity_extra_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -556,11 +565,11 @@ 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 (current_view_ == this && selected_) {
|
||||
hv_selection_color_ = FL_SELECTION_COLOR;
|
||||
hv_selection_text_color_ = fl_contrast(textcolor_, FL_SELECTION_COLOR);
|
||||
}
|
||||
current_pos = 0;
|
||||
current_pos_ = 0;
|
||||
|
||||
// Clip the drawing to the inside of the box...
|
||||
fl_push_clip(x() + Fl::box_dx(b), y() + Fl::box_dy(b),
|
||||
|
@ -613,7 +622,7 @@ Fl_Help_View::draw()
|
|||
fl_xyline(xx + x() - leftline_, yy + y() + 1,
|
||||
xx + x() - leftline_ + ww + xtra_ww);
|
||||
}
|
||||
current_pos = (int) (ptr-value_);
|
||||
current_pos_ = (int) (ptr-value_);
|
||||
|
||||
xx += ww;
|
||||
if ((fsize + 2) > hh)
|
||||
|
@ -631,7 +640,7 @@ Fl_Help_View::draw()
|
|||
if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
|
||||
xx + x() - leftline_ + buf.width());
|
||||
buf.clear();
|
||||
current_pos = (int) (ptr-value_);
|
||||
current_pos_ = (int) (ptr-value_);
|
||||
if (line < 31)
|
||||
line ++;
|
||||
xx = block->line[line];
|
||||
|
@ -662,7 +671,7 @@ Fl_Help_View::draw()
|
|||
if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
|
||||
xx + x() - leftline_ + ww);
|
||||
xx += ww;
|
||||
current_pos = (int) (ptr-value_);
|
||||
current_pos_ = (int) (ptr-value_);
|
||||
}
|
||||
|
||||
needspace = 0;
|
||||
|
@ -673,7 +682,7 @@ Fl_Help_View::draw()
|
|||
|
||||
while (isspace((*ptr)&255))
|
||||
ptr ++;
|
||||
current_pos = (int) (ptr-value_);
|
||||
current_pos_ = (int) (ptr-value_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,7 +714,7 @@ Fl_Help_View::draw()
|
|||
ptr ++;
|
||||
|
||||
// end of command reached, set the supposed start of printed eord here
|
||||
current_pos = (int) (ptr-value_);
|
||||
current_pos_ = (int) (ptr-value_);
|
||||
if (buf.cmp("HEAD"))
|
||||
head = 1;
|
||||
else if (buf.cmp("BR"))
|
||||
|
@ -964,7 +973,7 @@ Fl_Help_View::draw()
|
|||
needspace = 0;
|
||||
|
||||
ptr ++;
|
||||
current_pos = (int) (ptr-value_);
|
||||
current_pos_ = (int) (ptr-value_);
|
||||
}
|
||||
else if (isspace((*ptr)&255))
|
||||
{
|
||||
|
@ -982,7 +991,7 @@ Fl_Help_View::draw()
|
|||
}
|
||||
|
||||
ptr ++;
|
||||
if (!pre) current_pos = (int) (ptr-value_);
|
||||
if (!pre) current_pos_ = (int) (ptr-value_);
|
||||
needspace = 1;
|
||||
}
|
||||
else if (*ptr == '&') // process html entity
|
||||
|
@ -1036,7 +1045,7 @@ Fl_Help_View::draw()
|
|||
hv_draw(buf.c_str(), xx + x() - leftline_, yy + y());
|
||||
if (underline) fl_xyline(xx + x() - leftline_, yy + y() + 1,
|
||||
xx + x() - leftline_ + ww);
|
||||
current_pos = (int) (ptr-value_);
|
||||
current_pos_ = (int) (ptr-value_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2837,7 +2846,7 @@ void Fl_Help_View::follow_link(Fl_Help_Link *linkp)
|
|||
/** Removes the current text selection. */
|
||||
void Fl_Help_View::clear_selection()
|
||||
{
|
||||
if (current_view==this)
|
||||
if (current_view_==this)
|
||||
clear_global_selection();
|
||||
}
|
||||
/** Selects all the text in the view. */
|
||||
|
@ -2845,18 +2854,18 @@ 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;
|
||||
current_view_ = this;
|
||||
selection_drag_last_ = selection_last_ = (int) strlen(value_);
|
||||
selected_ = 1;
|
||||
}
|
||||
|
||||
void Fl_Help_View::clear_global_selection()
|
||||
{
|
||||
if (selected) redraw();
|
||||
selection_push_first = selection_push_last = 0;
|
||||
selection_drag_first = selection_drag_last = 0;
|
||||
selection_first = selection_last = 0;
|
||||
selected = 0;
|
||||
if (selected_) redraw();
|
||||
selection_push_first_ = selection_push_last_ = 0;
|
||||
selection_drag_first_ = selection_drag_last_ = 0;
|
||||
selection_first_ = selection_last_ = 0;
|
||||
selected_ = 0;
|
||||
}
|
||||
|
||||
char Fl_Help_View::begin_selection()
|
||||
|
@ -2865,18 +2874,18 @@ 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;
|
||||
mouse_x_ = Fl::event_x();
|
||||
mouse_y_ = Fl::event_y();
|
||||
draw_mode_ = 1;
|
||||
|
||||
current_view = this;
|
||||
current_view_ = this;
|
||||
fl_begin_offscreen(fl_help_view_buffer);
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
|
||||
draw_mode = 0;
|
||||
draw_mode_ = 0;
|
||||
|
||||
if (selection_push_last) return 1;
|
||||
if (selection_push_last_) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
@ -2885,38 +2894,44 @@ char Fl_Help_View::extend_selection()
|
|||
if (Fl::event_is_click())
|
||||
return 0;
|
||||
|
||||
// printf("old selection_first=%d, selection_last=%d\n",
|
||||
// selection_first, selection_last);
|
||||
// Give this widget the focus during the selection process. This will
|
||||
// deselect other text selection and make sure, we receive the Copy
|
||||
// keyboard shortcut.
|
||||
if (Fl::focus()!=this)
|
||||
Fl::focus(this);
|
||||
|
||||
int sf = selection_first, sl = selection_last;
|
||||
// printf("old selection_first_=%d, selection_last_=%d\n",
|
||||
// selection_first_, selection_last_);
|
||||
|
||||
selected = 1;
|
||||
mouse_x = Fl::event_x();
|
||||
mouse_y = Fl::event_y();
|
||||
draw_mode = 2;
|
||||
int sf = selection_first_, sl = selection_last_;
|
||||
|
||||
selected_ = 1;
|
||||
mouse_x_ = Fl::event_x();
|
||||
mouse_y_ = Fl::event_y();
|
||||
draw_mode_ = 2;
|
||||
|
||||
fl_begin_offscreen(fl_help_view_buffer);
|
||||
draw();
|
||||
fl_end_offscreen();
|
||||
|
||||
draw_mode = 0;
|
||||
draw_mode_ = 0;
|
||||
|
||||
if (selection_push_first < selection_drag_first) {
|
||||
selection_first = selection_push_first;
|
||||
if (selection_push_first_ < selection_drag_first_) {
|
||||
selection_first_ = selection_push_first_;
|
||||
} else {
|
||||
selection_first = selection_drag_first;
|
||||
selection_first_ = selection_drag_first_;
|
||||
}
|
||||
|
||||
if (selection_push_last > selection_drag_last) {
|
||||
selection_last = selection_push_last;
|
||||
if (selection_push_last_ > selection_drag_last_) {
|
||||
selection_last_ = selection_push_last_;
|
||||
} else {
|
||||
selection_last = selection_drag_last;
|
||||
selection_last_ = selection_drag_last_;
|
||||
}
|
||||
|
||||
// printf("new selection_first=%d, selection_last=%d\n",
|
||||
// selection_first, selection_last);
|
||||
// printf("new selection_first_=%d, selection_last_=%d\n",
|
||||
// selection_first_, selection_last_);
|
||||
|
||||
if (sf!=selection_first || sl!=selection_last) {
|
||||
if (sf!=selection_first_ || sl!=selection_last_) {
|
||||
// puts("REDRAW!!!\n");
|
||||
return 1;
|
||||
} else {
|
||||
|
@ -2947,7 +2962,7 @@ static unsigned int command(const char *cmd)
|
|||
|
||||
void Fl_Help_View::end_selection(int clipboard)
|
||||
{
|
||||
if (!selected || current_view!=this)
|
||||
if (!selected_ || current_view_!=this)
|
||||
return;
|
||||
// convert the select part of our html text into some kind of somewhat readable UTF-8
|
||||
// and store it in the selection buffer
|
||||
|
@ -2995,7 +3010,7 @@ void Fl_Help_View::end_selection(int clipboard)
|
|||
case CMD('d','d', 0 , 0 ): src = "\n - "; break;
|
||||
}
|
||||
int n = (int) (s-value_);
|
||||
if (src && n>selection_first && n<=selection_last) {
|
||||
if (src && n>selection_first_ && n<=selection_last_) {
|
||||
while (*src) {
|
||||
*d++ = *src++;
|
||||
}
|
||||
|
@ -3016,7 +3031,7 @@ void Fl_Help_View::end_selection(int clipboard)
|
|||
}
|
||||
}
|
||||
int n = (int) (s2-value_);
|
||||
if (n>selection_first && n<=selection_last) {
|
||||
if (n>selection_first_ && n<=selection_last_) {
|
||||
if (!pre && c < 256 && isspace(c)) c = ' ';
|
||||
if (p != ' ' || c != ' ') {
|
||||
if (s2 != s) { // c was an HTML entity
|
||||
|
@ -3026,7 +3041,7 @@ void Fl_Help_View::end_selection(int clipboard)
|
|||
}
|
||||
p = c;
|
||||
}
|
||||
if (n>selection_last) break; // stop parsing html after end of selection
|
||||
if (n>selection_last_) break; // stop parsing html after end of selection
|
||||
}
|
||||
*d = 0;
|
||||
Fl::copy(txt, (int) strlen(txt), clipboard);
|
||||
|
@ -3034,6 +3049,31 @@ void Fl_Help_View::end_selection(int clipboard)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/** Handles events in the widget. */
|
||||
int // O - 1 if we handled it, 0 otherwise
|
||||
Fl_Help_View::handle(int event) // I - Event to handle
|
||||
|
@ -3063,6 +3103,20 @@ Fl_Help_View::handle(int event) // I - Event to handle
|
|||
else fl_cursor(FL_CURSOR_DEFAULT);
|
||||
return 1;
|
||||
case FL_PUSH:
|
||||
if (Fl::event_button() == FL_RIGHT_MOUSE) {
|
||||
rmb_menu[0].label(copy_menu_text);
|
||||
if (text_selected())
|
||||
rmb_menu[0].activate();
|
||||
else
|
||||
rmb_menu[0].deactivate();
|
||||
fl_cursor(FL_CURSOR_DEFAULT);
|
||||
const Fl_Menu_Item *mi = rmb_menu->popup(Fl::event_x(), Fl::event_y());
|
||||
if (mi) switch (mi->argument()) {
|
||||
case 1:
|
||||
copy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Fl_Group::handle(event)) return 1;
|
||||
linkp = find_link(xx, yy);
|
||||
if (linkp) {
|
||||
|
@ -3084,7 +3138,7 @@ Fl_Help_View::handle(int event) // I - Event to handle
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
if (current_view==this && selection_push_last) {
|
||||
if (current_view_==this && selection_push_last_) {
|
||||
if (extend_selection()) redraw();
|
||||
fl_cursor(FL_CURSOR_INSERT);
|
||||
return 1;
|
||||
|
@ -3100,7 +3154,7 @@ Fl_Help_View::handle(int event) // I - Event to handle
|
|||
linkp = 0;
|
||||
return 1;
|
||||
}
|
||||
if (current_view==this && selection_push_last) {
|
||||
if (current_view_==this && selection_push_last_) {
|
||||
end_selection();
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue