[comp.sys.next] Customizing a ScrolView

scott@sage.uchicago.edu (Scott Deerwester) (02/03/91)

I wonder if anybody out there can help me with a problem.  I'm trying
to customize a ScrollView so that when I hit the mouse inside, it
selects an entire line (something like the summary window of the Mail
application) rather than characters within the line.  So I wrote a
class called Lines and overrode the - setSel method thus:

- setSel:(int)start:(int)end
{
	int newStart, newEnd;

	newStart = [self positionFromLine : [self lineFromPosition : start]];
	newEnd =   [self positionFromLine : [self lineFromPosition : end] + 1];

	[super setSel : newStart : newEnd];
	return self;
}

The problem is that it never gets called in response to the mouse.
I've looked at it in gdb, and neither it nor the Text setSel method
get called.  My guess is that ScrollView has handed off mouseDown
to the Text (Lines, in this case) delegate, which is probably the
ClipView or something known to it, which is doing the selection
itself.  I can't figure out how the selection could be done without
invoking the Text object's setSel method.  It happily selects whatever
characters I've moused, and never even invokes the above code.  If I
call the  customized setSel method explicitly, it works just fine.
Help! 
--
Scott Deerwester            | Internet: scott@tira.uchicago.edu  | ~{P;N,5B~}
Center for Information and  | Phone:    312-702-6948             |
   Language Studies         | 1100 E. 57th, CILS                 |
University of Chicago       | Chicago, IL 60637                  |

majka@cs.ubc.ca (Marc Majka) (02/05/91)

scott@sage.uchicago.edu (Scott Deerwester) writes:
>I wonder if anybody out there can help me with a problem.  I'm trying
>to customize a ScrollView so that when I hit the mouse inside, it
>selects an entire line (something like the summary window of the Mail
>application) rather than characters within the line.  So I wrote a
>class called Lines and overrode the - setSel method thus:

I solved this problem by subclassing Text.  My custom text object gets
attached as the ScrollView's DocView.  (Actually, it is the ScrollView's
ClipViews's DocView, but let's not get technical, shall we :-).  Anyway,
the idea is this:  My text object redefines mouseDown: as shown

- mouseDown:(NXEvent *)event
{
        NXPoint myPt = event->location;

        [super mouseDown :event];
        [self convertPoint :&myPt fromView :nil];
        [TheWatcher mouseSelected :&myPt];
        return self;
}

TheWatcher is the object that is doing all the work.  It catches appDidInit
(it is the Application's delegate), and sends my text object its id with the
message [TheText setWatcher :self].  The text object's method is just:

- setWatcher:sender
{
        TheWatcher = sender;
        return self;
}

Anyway, whenever the DocView gets a mouseDown, it tells my Watcher where it
hit.  The Watcher selects the line with something like the method below.
It determines the location of the selected line by dividing the y location
of the mouseDown by the line height of the text.  Since my application is
managing fixed length lines, it just multiplies by line length to determine
the text position.  You will need to do something different if your line
lengths vary.

- mouseSelected:(NXPoint *)pt
{
        int line, locn;

        line = pt->y / [TheText lineHeight];
        locn = line * LINELENGTH;
        [TheText setSel :locn :(locn + LINELENGTH)];

        return self;
}

Hope this helps!

---
Marc Majka
System Manager  -  UBC Computer Science