#include <sgtree.h>
Inheritance diagram for SGDisplayRootScroll:
Public Member Functions | |
SGDisplayRootScroll (SuperGallery *ParentGal) | |
SGDisplayRootScroll constructor (makes root nodes invisible by default). | |
virtual BOOL | HandleEvent (SGEventType EventType, void *EventInfo, SGMiscInfo *MiscInfo) |
Handles a SuperGallery DisplayTree event For this Scrollbar-providing version of the DisplayRoot node, adds a scrollbar at the right side of the window, and updates the event info appropriately to make the rest of the tree format to the left of that scroll bar. The scrollbar is 100% automated - any attempt to change the tree will result in the scrollbar updating as appropriate. | |
virtual void | SetScrollOffset (INT32 NewOffset, SGMiscInfo *MiscInfo) |
Changes the scroll offset, and if necessary, redraws the scroll bar. | |
virtual INT32 | GetScrollOffset (void) |
Returns the current scroll offset for the gallery display list represented in the tree. | |
virtual void | RedrawScrollBar (SGMiscInfo *MiscInfo) |
Causes the scroll bar, if any, to be redrawn, ensuring that it shows the correct information for the current format of the display list. | |
virtual BOOL | CalculateScrollRects (SGMiscInfo *MiscInfo, BOOL Translate, DocRect *UpButton, DocRect *DownButton, DocRect *Sausage, DocRect *PageUp=NULL, DocRect *PageDown=NULL, DocRect *ScrollRect=NULL) |
Determines where in the gadget the scroll bar rectangles are. Used by the SGScrollDragTarget in order to determine if the mouse pointer still lies over a given rectangle. | |
Public Attributes | |
INT32 | IndentedButton |
Protected Member Functions | |
virtual BOOL | CalculateSausageRect (SGMiscInfo *MiscInfo, DocRect *ScrollBarRect, DocRect *Result) |
Determines where within the given scroller the scroll 'sausage' (thumb) should be positioned to give the correct display. | |
Private Member Functions | |
CC_DECLARE_DYNAMIC (SGDisplayRootScroll) | |
Private Attributes | |
INT32 | ScrollOffset |
i.e. to get a gallery witha scrollbar, simply use this root node type, and everything just happens automatically for you.
Definition at line 1270 of file sgtree.h.
|
SGDisplayRootScroll constructor (makes root nodes invisible by default).
Definition at line 3779 of file sgtree.cpp. 03779 : SGDisplayRoot(ParentGal) 03780 { 03781 ScrollOffset = 0; 03782 IndentedButton = IBUTTON_NONE; 03783 03784 // Read the scroll bar width - use half of the normal scroll bar width (and is an even number) 03785 PORTNOTE("galleries", "hard wired scrollbar width"); 03786 ScrollBarWidth = 12; 03787 // ScrollBarWidth = (CScroller::GetScrollerSize() / 2) & 0xFE; 03788 03789 if (ScrollBarWidth < 10) // But make sure it lies within a sensible range 03790 ScrollBarWidth = 10; 03791 if (ScrollBarWidth > 100) 03792 ScrollBarWidth = 100; 03793 }
|
|
Determines where within the given scroller the scroll 'sausage' (thumb) should be positioned to give the correct display.
Definition at line 4041 of file sgtree.cpp. 04043 { 04044 INT32 PixelSize = MiscInfo->PixelSize; 04045 04046 // If the scroll bar hasn't got enough room to exist, it does not appear 04047 if (ScrollBarRect->hi.y - ScrollBarRect->lo.y < 5*PixelSize) 04048 return(FALSE); 04049 04050 *Result = *ScrollBarRect; 04051 Result->Inflate(-PixelSize); // Scroll sausage sits just inside the scroll rect 04052 Result->hi.x += PixelSize; // But the window border already does the 1-pixel black 04053 // line on the right, so we actually touch the scroll 04054 // rect on this edge. 04055 GridLockRect(MiscInfo, Result); 04056 04057 // If the sausage does not entirely fill the available space (we can scroll), then 04058 // scale and translate the sausage rect appropriately 04059 if (ScrollExtent > MiscInfo->WindowHeight) 04060 { 04061 // It is necessary to calculate the center of the sausage and grow it outwards 04062 // from that, so that we can ensure it never gets shorter that being a small square. 04063 04064 // Calculate the size of the proportional scroll sausage 04065 INT32 SausageHeight = (INT32) (((double)Result->Height()) * 04066 (((double)MiscInfo->WindowHeight) / (double)ScrollExtent)); 04067 04068 // Don't allow sausage to become smaller than a square 04069 if (SausageHeight < (ScrollBarWidth-2) * PixelSize) 04070 SausageHeight = (ScrollBarWidth-2) * PixelSize; 04071 04072 // BarTravel is the range in which the *center* of the scroll sausage can move - 04073 // this is limited by the overall bar height and the size of the scroll sausage 04074 INT32 BarTravel = Result->Height() - SausageHeight; 04075 04076 // Range in which the ScrollOffset is limited 04077 INT32 ScrollTravel = ScrollExtent - MiscInfo->WindowHeight; 04078 04079 // From which we calculate how far down the bar the sausage center appears 04080 double MidOffset = ((double)BarTravel * 04081 (((double)ScrollOffset) / (double)ScrollTravel)); 04082 04083 // Convert this into a position within the scroll rectangle (subtract from the top, 04084 // taking into account the gap at the top of the travel to contain half the sausage) 04085 MidOffset = (double) Result->hi.y - (((double)SausageHeight)/2 + MidOffset); 04086 04087 // Finally, shift and resize the scroll rectangle to generate the sausage rect 04088 Result->hi.y = (INT32) (-0.5 + MidOffset + SausageHeight/2); 04089 Result->lo.y = (INT32) (-0.5 + MidOffset - SausageHeight/2); 04090 GridLockRect(MiscInfo, Result); 04091 } 04092 04093 return(TRUE); 04094 }
|
|
Determines where in the gadget the scroll bar rectangles are. Used by the SGScrollDragTarget in order to determine if the mouse pointer still lies over a given rectangle.
Definition at line 3946 of file sgtree.cpp. 03951 { 03952 ERROR3IF(MiscInfo == NULL || UpButton == NULL || DownButton == NULL || Sausage == NULL, 03953 "SGDispayRootScroll::CalculateScrollRects - NULL params are illegal"); 03954 03955 // Calculate the strip into which the scrollbar must fit... 03956 INT32 ScrollWidth = DevicePixels(MiscInfo, ScrollBarWidth); 03957 03958 #ifdef _DEBUG 03959 if (((MiscInfo->MaxWidth - ScrollWidth) > MiscInfo->MaxWidth) || (0 > MiscInfo->WindowHeight)) 03960 { 03961 TRACE( _T("Bad MiscInfo in SGDispayRootScroll::CalculateScrollRects\n")); 03962 TRACE( _T(" MaxWidth = %d\n"), MiscInfo->MaxWidth); 03963 TRACE( _T(" WindowHeight = %d\n"), MiscInfo->WindowHeight); 03964 TRACE( _T(" DisplayMode = %d\n"), MiscInfo->DisplayMode); 03965 TRACE( _T(" PixelSize = %d\n"), MiscInfo->PixelSize); 03966 TRACE( _T("ScrollBarWidth = %d\n"), ScrollBarWidth); 03967 TRACE( _T("ScrollWidth = %d\n"), ScrollWidth); 03968 } 03969 #endif 03970 03971 DocRect ScrollRect(MiscInfo->MaxWidth - ScrollWidth, 0, 03972 MiscInfo->MaxWidth, MiscInfo->WindowHeight); 03973 03974 // Convert, if necessary, the position, into display-list offsets 03975 if (Translate) 03976 ScrollRect.Translate(0, -(ScrollOffset + MiscInfo->WindowHeight)); 03977 03978 GridLockRect(MiscInfo, &ScrollRect); 03979 03980 if (!ScrollRect.IsValid()) 03981 return(FALSE); 03982 03983 // Calculate the squares for the up/down scroll buttons 03984 *UpButton =ScrollRect; 03985 UpButton->lo.x += DevicePixels(MiscInfo, 1); 03986 UpButton->lo.y = (UpButton->hi.y - ScrollWidth) + DevicePixels(MiscInfo, 1); 03987 03988 *DownButton = *UpButton; 03989 DownButton->Translate(0, -(MiscInfo->WindowHeight - 03990 (ScrollWidth - DevicePixels(MiscInfo, 1)) )); 03991 03992 // And make the scroll rect include only the central strip 03993 ScrollRect.Inflate(0, -(ScrollWidth - DevicePixels(MiscInfo, 1))); 03994 03995 BOOL Result = CalculateSausageRect(MiscInfo, &ScrollRect, Sausage); 03996 03997 if (PageUp != NULL) 03998 { 03999 *PageUp = ScrollRect; 04000 PageUp->lo.y = Sausage->hi.y; 04001 } 04002 04003 if (PageDown != NULL) 04004 { 04005 *PageDown = ScrollRect; 04006 PageDown->hi.y = Sausage->lo.y; 04007 } 04008 04009 if (pScrollRect != NULL) 04010 *pScrollRect = ScrollRect; 04011 04012 return(Result); 04013 }
|
|
|
|
Returns the current scroll offset for the gallery display list represented in the tree.
Reimplemented from SGDisplayRoot. Definition at line 3906 of file sgtree.cpp. 03907 { 03908 return(ScrollOffset); 03909 }
|
|
Handles a SuperGallery DisplayTree event For this Scrollbar-providing version of the DisplayRoot node, adds a scrollbar at the right side of the window, and updates the event info appropriately to make the rest of the tree format to the left of that scroll bar. The scrollbar is 100% automated - any attempt to change the tree will result in the scrollbar updating as appropriate.
A node need not handle a specific event - if it does not handle it, it should return FALSE. Redraw and Formatting handlers should never return TRUE, as this will prevent the event from continuing through the tree. Non-leaf-nodes must call SGDisplayNode::GiveEventToMyChildren in order to pass the event down the tree.
Reimplemented from SGDisplayRoot. Definition at line 4136 of file sgtree.cpp. 04138 { 04139 // THUMBMSG and BGFLUSH can be broadcast with MiscInfo == NULL. We ignore these msgs 04140 // so we just pass them on to the base class immediately. 04141 if (MiscInfo == NULL) 04142 return(SGDisplayRoot::HandleEvent(EventType, EventInfo, MiscInfo)); 04143 04144 SGMiscInfo NewMiscInfo(*MiscInfo); // Ensure we don't corrupt the one passed in 04145 04146 // Calculate the strip into which the scrollbar must fit... 04147 INT32 ScrollWidth = DevicePixels(MiscInfo, ScrollBarWidth); 04148 04149 DocRect ScrollRect; 04150 DocRect UpButton; 04151 DocRect DownButton; 04152 DocRect PageUp; 04153 DocRect PageDown; 04154 DocRect SausageRect; 04155 BOOL HasScrollBar = CalculateScrollRects(MiscInfo, TRUE, 04156 &UpButton, &DownButton, &SausageRect, 04157 &PageUp, &PageDown, &ScrollRect); 04158 04159 // Convince the DisplayTree the scroll area is outside the region they can use 04160 // We add 1 pixel to put a 1-pixel white gap between the scrollbar and the right end of all items 04161 NewMiscInfo.MaxWidth -= ScrollWidth; 04162 04163 // Remember what the scroll extent used to be. If formatting causes a chnage to the extent, 04164 // we'll redraw ourself to make sure that our display is up to date. 04165 INT32 OldScrollExtent = ScrollExtent; 04166 04167 switch (EventType) 04168 { 04169 case SGEVENT_FORMAT: 04170 if (HasScrollBar) 04171 { 04172 SGFormatInfo *FormatInfo = GetFormatInfo(EventType, EventInfo); 04173 04174 // Reset AvailableWidth so the first line doesn't overwrite the scrollbar! 04175 FormatInfo->AvailableWidth = NewMiscInfo.MaxWidth; 04176 } 04177 break; 04178 04179 04180 case SGEVENT_REDRAW: 04181 // Does nothing here - redraw is now delayed until after we have called all our 04182 // children, so that rampant clipping problems in the font gallery do not cause 04183 // the scrollbar to be left in an overwritten state. 04184 break; 04185 04186 04187 case SGEVENT_MOUSECLICK: 04188 if (HasScrollBar && ScrollExtent > 0) 04189 { 04190 SGMouseInfo *MouseInfo = GetMouseInfo(EventType, EventInfo); 04191 SGDragType DragType = SGDRAG_NONE; 04192 04193 if (ScrollRect.ContainsCoord(MouseInfo->Position)) 04194 { 04195 if (SausageRect.ContainsCoord(MouseInfo->Position)) 04196 DragType = SGDRAG_SAUSAGE; 04197 else if (SausageRect.hi.y < MouseInfo->Position.y) 04198 DragType = SGDRAG_PAGEUP; 04199 else if (SausageRect.lo.y > MouseInfo->Position.y) 04200 DragType = SGDRAG_PAGEDOWN; 04201 else 04202 return(TRUE); 04203 } 04204 04205 if (DragType == SGDRAG_NONE && UpButton.ContainsCoord(MouseInfo->Position)) 04206 DragType = SGDRAG_SCROLLUP; 04207 04208 if (DragType == SGDRAG_NONE && DownButton.ContainsCoord(MouseInfo->Position)) 04209 DragType = SGDRAG_SCROLLDOWN; 04210 04211 if (DragType != SGDRAG_NONE) 04212 { 04213 SGScrollDragInfo *DragInfo = 04214 new SGScrollDragInfo(this, DragType, MiscInfo, 04215 SausageRect.hi.y - MouseInfo->Position.y, 04216 MouseInfo->MenuClick); 04217 04218 if (DragInfo != NULL) 04219 DragManagerOp::StartDrag(DragInfo, GetListWindow()); 04220 } 04221 } 04222 break; 04223 04224 04225 case SGEVENT_DRAGSTARTED: 04226 { 04227 DragMessage *Msg = GetDragInfo(EventType, EventInfo); 04228 04229 // Is it a Drag Started message? 04230 if (Msg->State == DragMessage::DRAGSTARTED) 04231 { 04232 // Is it a SuperGallery scroll drag? 04233 // And is it a scroll drag for THIS display tree? 04234 if (Msg->pInfo->IsKindOf(CC_RUNTIME_CLASS(SGScrollDragInfo)) && 04235 ((SGScrollDragInfo *)(Msg->pInfo))->GetDragRootNode() == this) 04236 { 04237 SuperGallery *ParentGallery = GetParentGallery(); 04238 04239 // AMB comment out assignment to variable as variable is unused. Can this be right? 04240 /* SGScrollDragTarget *DragTarget = */ 04241 new SGScrollDragTarget(ParentGallery, 04242 ParentGallery->GetListGadgetID()); 04243 } 04244 } 04245 } 04246 break; 04247 04248 default: 04249 break; 04250 } 04251 04252 // And pass the event on to the tree via our base class handler 04253 BOOL Result = SGDisplayRoot::HandleEvent(EventType, EventInfo, 04254 (HasScrollBar) ? &NewMiscInfo : MiscInfo); 04255 04256 if (EventType == SGEVENT_FORMAT && ScrollExtent != OldScrollExtent && HasScrollBar) 04257 { 04258 // The scroll extent has changed as a result of this reformat. 04259 // We'd better invalidate the scrollbar rectangle to make sure it's up to date 04260 SuperGallery *ParentGal = GetParentGallery(); 04261 04262 04263 // We modify the scrollbar rectangle before invalidating it - if the extent has changed, 04264 // the scrollbar may have been scrolled off the visible area!! 04265 // The easiest way to redraw it is to just redraw everything down the right side of the extent 04266 ScrollRect.hi.y = 0; 04267 ScrollRect.lo.y = -(ScrollExtent + MiscInfo->WindowHeight); 04268 ParentGal->ForceRedrawOfArea(&ScrollRect); 04269 04270 // If the extent has got smaller, ensure the invalid redraw region includes 04271 // everything to the very bottom of the list 04272 SGFormatInfo *FormatInfo = GetFormatInfo(EventType, EventInfo); 04273 if (FormatInfo->AccumulateBounds) 04274 FormatInfo->InvalidBounds.lo.y = min(-OldScrollExtent, -ScrollExtent); 04275 } 04276 04277 if (EventType == SGEVENT_REDRAW && HasScrollBar) // If room for a scrollbar, draw it 04278 { 04279 // Redraw is now left until after all children have been redrawn, as the font gallery 04280 // has a clipping problem where it was overwriting the scrollbar area. By drawing last 04281 // we at least end up in the correct screen display state. 04282 INT32 PixelSize = DevicePixels(MiscInfo, 1); 04283 04284 SGRedrawInfo *RedrawInfo = GetRedrawInfo(EventType, EventInfo); 04285 RenderRegion *Renderer = RedrawInfo->Renderer; 04286 04287 StartRendering(RedrawInfo, MiscInfo); 04288 04289 // Note that we call the base class, so we can rely on it to clear the 04290 // background of the area outside the scrollbar 04291 04292 // If we don't need to redraw anything, then we, er... don't redraw anything 04293 if (ScrollRect.IsIntersectedWith(RedrawInfo->Bounds) || 04294 UpButton.IsIntersectedWith(RedrawInfo->Bounds) || 04295 DownButton.IsIntersectedWith(RedrawInfo->Bounds)) 04296 { 04297 DialogColourInfo RedrawColours; 04298 04299 // Fill the page-up and down rectangles with background colour. 04300 // We move the left and top/bottom edges by 1 pixel to accomodate 04301 // the black border lines that we draw around these areas. 04302 Renderer->SetLineWidth(0); 04303 DocColour trans(COLOUR_TRANS); 04304 Renderer->SetLineColour(trans); 04305 Renderer->SetFillColour(RedrawColours.ButtonFace()); 04306 04307 PageUp.lo.x += PixelSize; 04308 PageUp.hi.y -= PixelSize; 04309 if (PageUp.IsValid()) 04310 Renderer->DrawRect(&PageUp); 04311 04312 PageDown.lo.x += PixelSize; 04313 PageDown.lo.y += PixelSize; 04314 if (PageDown.IsValid()) 04315 Renderer->DrawRect(&PageDown); 04316 04317 // Draw a 1-pixel black border around the region 04318 // (down left edge and between scroll bar and arrows) 04319 // We draw these lines as filled rectangles to avoid the fact that lines 04320 // draw in different blimming places in different render regions 04321 DocColour black(COLOUR_BLACK); 04322 Renderer->SetFillColour(black); 04323 04324 Renderer->DrawPixelLine(DocCoord(ScrollRect.lo.x, DownButton.lo.y), 04325 DocCoord(ScrollRect.lo.x, UpButton.hi.y)); 04326 Renderer->DrawPixelLine(DocCoord(ScrollRect.lo.x, ScrollRect.hi.y - PixelSize), 04327 DocCoord(ScrollRect.hi.x, ScrollRect.hi.y - PixelSize)); 04328 Renderer->DrawPixelLine(DocCoord(ScrollRect.lo.x, ScrollRect.lo.y), 04329 DocCoord(ScrollRect.hi.x, ScrollRect.lo.y)); 04330 04331 // Draw the scroll sausage 04332 DrawPlinth(RedrawInfo, MiscInfo, &RedrawColours, &SausageRect, FALSE); 04333 04334 Renderer->DrawPixelLine(DocCoord(ScrollRect.lo.x, SausageRect.hi.y), 04335 DocCoord(ScrollRect.hi.x, SausageRect.hi.y)); 04336 Renderer->DrawPixelLine(DocCoord(ScrollRect.lo.x, SausageRect.lo.y - PixelSize), 04337 DocCoord(ScrollRect.hi.x, SausageRect.lo.y - PixelSize)); 04338 04339 // Draw the scroll-up and scroll-down buttons 04340 DrawPlinth(RedrawInfo, MiscInfo, &RedrawColours, 04341 &UpButton, (IndentedButton == IBUTTON_UP), 04342 _R(IDB_GALLERY_SCROLLUP)); 04343 04344 DrawPlinth(RedrawInfo, MiscInfo, &RedrawColours, 04345 &DownButton, (IndentedButton == IBUTTON_DOWN), 04346 _R(IDB_GALLERY_SCROLLDOWN)); 04347 } 04348 04349 StopRendering(RedrawInfo, MiscInfo); 04350 } 04351 04352 return(Result); 04353 }
|
|
Causes the scroll bar, if any, to be redrawn, ensuring that it shows the correct information for the current format of the display list.
Reimplemented from SGDisplayRoot. Definition at line 4373 of file sgtree.cpp. 04374 { 04375 // Calculate the strip into which the scrollbar must fit... 04376 INT32 ScrollWidth = DevicePixels(MiscInfo, ScrollBarWidth); 04377 04378 DocRect ScrollRect(MiscInfo->MaxWidth - ScrollWidth, -MiscInfo->WindowHeight, 04379 MiscInfo->MaxWidth, 0); 04380 ScrollRect.Translate(0, -ScrollOffset); 04381 GridLockRect(MiscInfo, &ScrollRect); 04382 04383 GetParentGallery()->ForceRedrawOfArea(&ScrollRect); 04384 }
|
|
Changes the scroll offset, and if necessary, redraws the scroll bar.
Notes: To ensure that the current scroll offset is within bounds, call SetScrollOffset(GetScrollOffset(), MiscInfo);
Reimplemented from SGDisplayRoot. Definition at line 3818 of file sgtree.cpp. 03819 { 03820 // Ensure we don't scroll out of bounds 03821 if (NewOffset > ScrollExtent - MiscInfo->WindowHeight) 03822 NewOffset = ScrollExtent - MiscInfo->WindowHeight; 03823 03824 if (NewOffset < 0) 03825 NewOffset = 0; 03826 03827 // Make sure the scroll offset is aligned tidily with the output pixel grid 03828 GridLock(MiscInfo, NewOffset); 03829 03830 // And if it has changed, set the new scroll offset, and scroll the window 03831 if (NewOffset != ScrollOffset) 03832 { 03833 DocCoord ScrollBy(0, NewOffset - ScrollOffset); 03834 03835 if (!GetParentGallery()->AreYouRedrawingNow()) 03836 { 03837 // A normal scroll - we are not inside the redraw code, so we can safely 03838 // assume that the screen display is up to date (and therefore can be scrolled 03839 // with 'ScrollArea') and that it is safe to invoke redraw. 03840 03841 DocRect ScrollRect(0, 0, MiscInfo->MaxWidth - DevicePixels(MiscInfo, ScrollBarWidth), 03842 MiscInfo->WindowHeight); 03843 03844 // Scroll the window. During the scroll, we make sure that the drag manager 03845 // has removed any eor or solid drag blobs from screen, so we don't copy 03846 // them as part of the scroll! 03847 DragManagerOp::RedrawStarting(GetParentGallery()->WindowID, 03848 GetParentGallery()->GetListGadgetID()); 03849 03850 // And scroll 03851 GetParentGallery()->ScrollArea(&ScrollRect, &ScrollBy); 03852 03853 // Set the new scroll offset, using the gridlocked value returned from ScrollArea 03854 ScrollOffset += ScrollBy.y; 03855 03856 // Redraw immediately. If we scroll only a little bit, and do not redraw 03857 // immediately, we get a small horizontal strip, plus the vertical scroll bar 03858 // region, and so the redraw bounds is the entire window, so we redraw heaps 03859 // more than actually changes, thus making scrolling dead slow. 03860 GetParentGallery()->PaintListNow(); 03861 03862 // And redraw the proportional scrollbar 03863 DocRect ScrollBarRect(MiscInfo->MaxWidth - DevicePixels(MiscInfo, ScrollBarWidth), 03864 -ScrollExtent, 03865 MiscInfo->MaxWidth, 0); 03866 GetParentGallery()->ForceRedrawOfArea(&ScrollBarRect); 03867 03868 // And finally, force another immediate repaint of the list gadget 03869 GetParentGallery()->PaintListNow(); 03870 03871 DragManagerOp::RedrawFinished(); 03872 } 03873 else 03874 { 03875 // Awooga! We have been forced to fix the scroll offset during a redraw (probably 03876 // because the window size has changed). We thus change the scroll offset, but 03877 // do not try to redraw or anything - hopefully the pending redraw will handle 03878 // everything. 03879 03880 // Set the new scroll offset, using the gridlocked value returned from ScrollArea 03881 ScrollOffset += ScrollBy.y; 03882 } 03883 } 03884 }
|
|
|
|
|