|
From: jeroen <je...@fo...> - 2001-12-11 05:43:15
|
On Monday 10 December 2001 23:04, you wrote: > Hi, > I'm brand new to FOX, but have already had fairly good success > creating a GUI with fox for an application I'm writing. > I'm writing an audio editor for linux and I'm trying to create a new > FOX widget, FXWaveView that's derived from another FOX class. > What this widget has to do specifically, is draw the wave form... It's > going to detect mouse clicks to make selections and such... and I've > already been successful drawing the waveform on a canvas (just > separately in a test app).... What I need to know is: what's the best > way to implement scrolling here... > > The widget will be given a pointer to a loaded sound object from which > it can get the audio data to draw. I'm going to make a zoom parameter > that says at what level to draw the wave form... And when the zoom is > such that the wave form is wider than the canvas I need to be able to > scroll it... I'd like the scroll bars to always be visible and not come > and go as needed... I didn't know if it'd be best to instantiate a > canvas and a scroll bar (actually 2 scroll bars.. Vertand Horz, but I'm > just worried about Horz right now)) and just get notified when the > scroll bar is scrolled.. Also, I'd like to have auto scrolling available > where it will scroll if you're holding the mouse button down and move > the mouse outside the canvas.... Well, I saw that FXScrollArea had some > functionality like this.... But I tried using FXScrollArea and putting > a canvas inside, and I could not for my life get the H scroll bar to be > able to scroll... how do I set the content size of the FXScrollArea... > Am I thinking right that the canvas will always be at 0,0-w,h in there > and I'll just draw on it but offset the data I'm drawing based on the H > scroll bar's position? > Or is there a better way altogether for doing this? > > Thanks, > Davy You're on the right track using FXScrollArea for this; it supports auto-scrolling, i.e. when you get near the edge it starts to scroll (the speed is proportional to the closeness to the edge). FXScrollArea is meant as a base class. At the very least, you should implement: virtual FXint getContentWidth(); virtual FXint getContentHeight(); These two will measure the content size (in your case this may depend on the zoom factor) and return that. Note, sometimes the content size must be obtained via painful amount of computation (e.g. iterating over all wave samples and measuring the peaks so as to determine vertical size). In that case it is customary to keep member variables representing the computed size and return that, and only recompute them when there is reason to believe content may have changed. long onPaint(FXObject*,FXSelector,void*); Of course, this should paint the waveform. Note that the content is offset by pos_x and pos_y. These numbers are negative! long onLeftBtnPress(FXObject*,FXSelector,void*); Initiate selection operation. long onLeftBtnRelease(FXObject*,FXSelector,void*); End selection operation. long onRightBtnPress(FXObject*,FXSelector,void*); Start right-mouse scroll. long onRightBtnRelease(FXObject*,FXSelector,void*); End right mouse scroll; if we didn't move the mouse, then this may also popup a context menu. long onMotion(FXObject*,FXSelector,void*); If we were right-mouse scrolling, call setPosition() to adjust the scroll position accordingly. If we were selecting, call startAutoScroll(). This tests if we're close to the edge. If startAutoScroll() returns TRUE then simply return. Otherwise, we're not close to the edge and you should process the mouse coords to select the appropriate audio samples. long onAutoScroll(FXObject*,FXSelector,void*); This handler is a kind-of mouse moved message issued while the mouse is more-or-less standing still near an edge. The implementation should call FXScrollArea::onAutoScroll() then perform similar code as in onMotion() to select audio samples. If you're not scrolling ALL of the content, you may have to implement virtual void moveContents(FXint x,FXint y); To BLIT the fragment that *is* scrolled. For example some tick marks on the left or right will probably not be scrolled (see FXTable for an extreme case). In some cases, a widget needs to update some info when its resized; in this case you will re-implement: virtual void layout(); The implementation should call FXScrollArea::layout() to place the scrollbars. You can perform some extra stuff before or after. This may look a bit complex, but I think if you look at FXList and FXImageView, you'll see that your code will be very similar to that. FXScrollArea does a lot already (placing scrollbars, based on the viewport and content size, and the autoscrolling timer management. === If you want to go all-out, you can extend this with clipboard, drag-and-drop, selection support. This will allow cut-and-paste between FXWaveView and other WAV aware applications (provided the mime-types match). Good luck. Jeroen |