summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2005-08-10 23:11:51 +0000
committerMatthias Melcher <fltk@matthiasm.com>2005-08-10 23:11:51 +0000
commitaf39242da6b5aa97ecbe4d197b1698906b347689 (patch)
tree7eb9988aec5fd55d73653d25e2980e7e5ea42642
parent7410f80a844d0a4fdd4bc423bc792d3acb28a152 (diff)
Fl_Text_Display now auto-scrolls in all directions (STR #915). This is implemented using a timer event. The scroll speed is proportional to the distance of the cursor to the text area
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@4502 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--CHANGES2
-rw-r--r--FL/Fl_Text_Display.H2
-rw-r--r--src/Fl_Text_Display.cxx90
3 files changed, 86 insertions, 8 deletions
diff --git a/CHANGES b/CHANGES
index 16d48ecf7..4a9a2240f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,8 @@ CHANGES IN FLTK 1.1.7
- Documentation fixes (STR #571, STR #648, STR #692, STR
#730, STR #744, STR #745, STR #931, STR #942, STR #960,
STR #969)
+ - Fl_Text_Display now auto-scrolls in all
+ directions (STR #915)
- Borderless windows will not show in the taskbar anymore
on X11 (STR #933)
- Fixed event_text() field on FL_DND_* event on
diff --git a/FL/Fl_Text_Display.H b/FL/Fl_Text_Display.H
index 84e937b60..7e94ef001 100644
--- a/FL/Fl_Text_Display.H
+++ b/FL/Fl_Text_Display.H
@@ -166,6 +166,8 @@ class FL_EXPORT Fl_Text_Display: public Fl_Group {
int position_to_line( int pos, int* lineNum );
int string_width(const char* string, int length, int style);
+ static void scroll_timer_cb(void*);
+
static void buffer_predelete_cb(int pos, int nDeleted, void* cbArg);
static void buffer_modified_cb(int pos, int nInserted, int nDeleted,
int nRestyled, const char* deletedText,
diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx
index 2b9e56fd6..a4b020f26 100644
--- a/src/Fl_Text_Display.cxx
+++ b/src/Fl_Text_Display.cxx
@@ -66,6 +66,13 @@ static int max( int i1, int i2 );
static int min( int i1, int i2 );
static int countlines( const char *string );
+/* The variables below are used in a timer event to allow smooth
+ scrolling of the text area when the pointer has left the area. */
+static int scroll_direction = 0;
+static int scroll_amount = 0;
+static int scroll_y = 0;
+static int scroll_x = 0;
+
// CET - FIXME
#define TMPFONTWIDTH 6
@@ -147,6 +154,10 @@ Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l)
** freed, nor are the style buffer or style table.
*/
Fl_Text_Display::~Fl_Text_Display() {
+ if (scroll_direction) {
+ Fl::remove_timeout(scroll_timer_cb, this);
+ scroll_direction = 0;
+ }
if (mBuffer) {
mBuffer->remove_modify_callback(buffer_modified_cb, this);
mBuffer->remove_predelete_callback(buffer_predelete_cb, this);
@@ -3031,6 +3042,37 @@ void fl_text_drag_me(int pos, Fl_Text_Display* d) {
}
}
+// This timer event scrolls the text view proportionally to
+// how far the mouse pointer has left the text area. This
+// allows for smooth scrolling without "wiggeling" the mouse.
+void Fl_Text_Display::scroll_timer_cb(void *user_data) {
+ Fl_Text_Display *w = (Fl_Text_Display*)user_data;
+ int pos;
+ switch (scroll_direction) {
+ case 1: // mouse is to the right, scroll left
+ w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount);
+ pos = w->xy_to_position(w->text_area.x + w->text_area.w, scroll_y, CURSOR_POS);
+ break;
+ case 2: // mouse is to the left, scroll right
+ w->scroll(w->mTopLineNum, w->mHorizOffset + scroll_amount);
+ pos = w->xy_to_position(w->text_area.x, scroll_y, CURSOR_POS);
+ break;
+ case 3: // mouse is above, scroll down
+ w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset);
+ pos = w->xy_to_position(scroll_x, w->text_area.y, CURSOR_POS);
+ break;
+ case 4: // mouse is below, scroll up
+ w->scroll(w->mTopLineNum + scroll_amount, w->mHorizOffset);
+ pos = w->xy_to_position(scroll_x, w->text_area.y + w->text_area.h, CURSOR_POS);
+ break;
+ default:
+ return;
+ }
+ fl_text_drag_me(pos, w);
+ Fl::repeat_timeout(.1, scroll_timer_cb, user_data);
+}
+
+
int Fl_Text_Display::handle(int event) {
if (!buffer()) return 0;
// This isn't very elegant!
@@ -3089,21 +3131,53 @@ int Fl_Text_Display::handle(int event) {
case FL_DRAG: {
if (dragType < 0) return 1;
int X = Fl::event_x(), Y = Fl::event_y(), pos;
+ // if we leave the text_area, we start a timer event
+ // that will take care of scrolling and selecting
if (Y < text_area.y) {
- move_up();
- scroll(mTopLineNum - 1, mHorizOffset);
- pos = insert_position();
+ scroll_x = X;
+ scroll_amount = (Y - text_area.y) / 5 - 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 3;
} else if (Y >= text_area.y+text_area.h) {
- move_down();
- scroll(mTopLineNum + 1, mHorizOffset);
- pos = insert_position();
- } else pos = xy_to_position(X, Y, CURSOR_POS);
- fl_text_drag_me(pos, this);
+ scroll_x = X;
+ scroll_amount = (Y - text_area.y - text_area.h) / 5 + 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 4;
+ } else if (X < text_area.x) {
+ scroll_y = Y;
+ scroll_amount = (X - text_area.x) / 2 - 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 2;
+ } else if (X >= text_area.x+text_area.w) {
+ scroll_y = Y;
+ scroll_amount = (X - text_area.x - text_area.w) / 2 + 1;
+ if (!scroll_direction) {
+ Fl::add_timeout(.01, scroll_timer_cb, this);
+ }
+ scroll_direction = 1;
+ } else {
+ if (scroll_direction) {
+ Fl::remove_timeout(scroll_timer_cb, this);
+ scroll_direction = 0;
+ }
+ pos = xy_to_position(X, Y, CURSOR_POS);
+ fl_text_drag_me(pos, this);
+ }
return 1;
}
case FL_RELEASE: {
dragging = 0;
+ if (scroll_direction) {
+ Fl::remove_timeout(scroll_timer_cb, this);
+ scroll_direction = 0;
+ }
// convert from WORD or LINE selection to CHAR
if (insert_position() >= dragPos)