Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

CEGUIListHeaderSegment.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002         filename:       CEGUIListHeaderSegment.cpp
00003         created:        15/6/2004
00004         author:         Paul D Turner
00005         
00006         purpose:        Implementation of List header segment widget.
00007 *************************************************************************/
00008 /*************************************************************************
00009     Crazy Eddie's GUI System (http://www.cegui.org.uk)
00010     Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
00011 
00012     This library is free software; you can redistribute it and/or
00013     modify it under the terms of the GNU Lesser General Public
00014     License as published by the Free Software Foundation; either
00015     version 2.1 of the License, or (at your option) any later version.
00016 
00017     This library is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020     Lesser General Public License for more details.
00021 
00022     You should have received a copy of the GNU Lesser General Public
00023     License along with this library; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 *************************************************************************/
00026 #include "elements/CEGUIListHeaderSegment.h"
00027 #include "CEGUIMouseCursor.h"
00028 
00029 
00030 // Start of CEGUI namespace section
00031 namespace CEGUI
00032 {
00033 const String ListHeaderSegment::EventNamespace("ListHeaderSegment");
00034 
00035 /*************************************************************************
00036         Properties for this class
00037 *************************************************************************/
00038 ListHeaderSegmentProperties::Clickable          ListHeaderSegment::d_clickableProperty;
00039 ListHeaderSegmentProperties::Dragable           ListHeaderSegment::d_dragableProperty;
00040 ListHeaderSegmentProperties::Sizable            ListHeaderSegment::d_sizableProperty;
00041 ListHeaderSegmentProperties::SortDirection      ListHeaderSegment::d_sortDirectionProperty;
00042 
00043 
00044 /*************************************************************************
00045         Constants
00046 *************************************************************************/
00047 // Event names
00048 const String ListHeaderSegment::EventSegmentClicked( (utf8*)"SegmentClicked" );
00049 const String ListHeaderSegment::EventSplitterDoubleClicked( (utf8*)"SplitterDoubleClicked" );
00050 const String ListHeaderSegment::EventSizingSettingChanged( (utf8*)"SizingSettingChanged" );
00051 const String ListHeaderSegment::EventSortDirectionChanged( (utf8*)"SortDirectionChanged" );
00052 const String ListHeaderSegment::EventMovableSettingChanged( (utf8*)"MovableSettingChanged" );
00053 const String ListHeaderSegment::EventSegmentDragStart( (utf8*)"SegmentDragStart" );
00054 const String ListHeaderSegment::EventSegmentDragStop( (utf8*)"SegmentDragStop" );
00055 const String ListHeaderSegment::EventSegmentDragPositionChanged( (utf8*)"SegmentDragPositionChanged" );
00056 const String ListHeaderSegment::EventSegmentSized( (utf8*)"SegmentSized" );
00057 const String ListHeaderSegment::EventClickableSettingChanged( (utf8*)"ClickableSettingChanged" );
00058 
00059 // Defaults
00060 const float     ListHeaderSegment::DefaultSizingArea    = 8.0f;
00061 const float     ListHeaderSegment::SegmentMoveThreshold = 12.0f;
00062 
00063 
00064 /*************************************************************************
00065         Constructor for list header segment base class  
00066 *************************************************************************/
00067 ListHeaderSegment::ListHeaderSegment(const String& type, const String& name) :
00068         Window(type, name),
00069         d_sizingMouseCursor(NULL),
00070         d_movingMouseCursor(NULL),
00071         d_splitterSize(DefaultSizingArea),
00072         d_splitterHover(false),
00073         d_dragSizing(false),
00074         d_sortDir(None),
00075         d_segmentHover(false),
00076         d_segmentPushed(false),
00077         d_sizingEnabled(true),
00078         d_movingEnabled(true),
00079         d_dragMoving(false),
00080         d_allowClicks(true)
00081 {
00082         addHeaderSegmentEvents();
00083         addHeaderSegmentProperties();
00084 }
00085 
00086 
00087 /*************************************************************************
00088         Destructor for list header segment base class.  
00089 *************************************************************************/
00090 ListHeaderSegment::~ListHeaderSegment(void)
00091 {
00092 }
00093 
00094 
00095 /*************************************************************************
00096         Set whether this segment can be sized.
00097 *************************************************************************/
00098 void ListHeaderSegment::setSizingEnabled(bool setting)
00099 {
00100         if (d_sizingEnabled != setting)
00101         {
00102                 d_sizingEnabled = setting;
00103 
00104                 // if sizing is now disabled, ensure sizing operation is cancelled
00105                 if (!d_sizingEnabled && d_dragSizing)
00106                 {
00107                         releaseInput();
00108                 }
00109 
00110                 WindowEventArgs args(this);
00111                 onSizingSettingChanged(args);
00112         }
00113 
00114 }
00115 
00116 
00117 /*************************************************************************
00118         Set the current sort direction set for this segment.    
00119 *************************************************************************/
00120 void ListHeaderSegment::setSortDirection(SortDirection sort_dir)
00121 {
00122         if (d_sortDir != sort_dir)
00123         {
00124                 d_sortDir = sort_dir;
00125 
00126                 WindowEventArgs args(this);
00127                 onSortDirectionChanged(args);
00128 
00129                 requestRedraw();
00130         }
00131 
00132 }
00133 
00134 
00135 /*************************************************************************
00136         Set whether drag moving is allowed for this segment.    
00137 *************************************************************************/
00138 void ListHeaderSegment::setDragMovingEnabled(bool setting)
00139 {
00140         if (d_movingEnabled != setting)
00141         {
00142                 d_movingEnabled = setting;
00143 
00144                 WindowEventArgs args(this);
00145                 onMovableSettingChanged(args);
00146         }
00147 
00148 }
00149 
00150 
00151 /*************************************************************************
00152         Set whether the segment is clickable.
00153 *************************************************************************/
00154 void ListHeaderSegment::setClickable(bool setting)
00155 {
00156         if (d_allowClicks != setting)
00157         {
00158                 d_allowClicks = setting;
00159 
00160                 WindowEventArgs args(this);
00161                 onClickableSettingChanged(args);
00162         }
00163 
00164 }
00165 
00166 
00167 /*************************************************************************
00168         Add list header segment specific events
00169 *************************************************************************/
00170 void ListHeaderSegment::addHeaderSegmentEvents(void)
00171 {
00172         addEvent(EventSortDirectionChanged);
00173         addEvent(EventSizingSettingChanged);
00174         addEvent(EventSplitterDoubleClicked);
00175         addEvent(EventSegmentClicked);
00176         addEvent(EventSegmentDragStart);
00177         addEvent(EventSegmentDragStop);
00178         addEvent(EventSegmentDragPositionChanged);
00179         addEvent(EventMovableSettingChanged);
00180         addEvent(EventSegmentSized);
00181         addEvent(EventClickableSettingChanged);
00182 }
00183 
00184 
00185 
00186 /*************************************************************************
00187         Handler called when segment is clicked. 
00188 *************************************************************************/
00189 void ListHeaderSegment::onSegmentClicked(WindowEventArgs& e)
00190 {
00191         fireEvent(EventSegmentClicked, e, EventNamespace);
00192 }
00193 
00194 
00195 /*************************************************************************
00196         Handler called when the sizer/splitter is double-clicked.       
00197 *************************************************************************/
00198 void ListHeaderSegment::onSplitterDoubleClicked(WindowEventArgs& e)
00199 {
00200         fireEvent(EventSplitterDoubleClicked, e, EventNamespace);
00201 }
00202 
00203 
00204 /*************************************************************************
00205         Handler called when sizing setting changes.
00206 *************************************************************************/
00207 void ListHeaderSegment::onSizingSettingChanged(WindowEventArgs& e)
00208 {
00209         fireEvent(EventSizingSettingChanged, e, EventNamespace);
00210 }
00211 
00212 
00213 /*************************************************************************
00214         Handler called when the sort direction value changes.
00215 *************************************************************************/
00216 void ListHeaderSegment::onSortDirectionChanged(WindowEventArgs& e)
00217 {
00218         requestRedraw();
00219         fireEvent(EventSortDirectionChanged, e, EventNamespace);
00220 }
00221 
00222 
00223 /*************************************************************************
00224         Handler called when the drag-movable setting is changed.
00225 *************************************************************************/
00226 void ListHeaderSegment::onMovableSettingChanged(WindowEventArgs& e)
00227 {
00228         fireEvent(EventMovableSettingChanged, e, EventNamespace);
00229 }
00230 
00231 
00232 /*************************************************************************
00233         Handler called when the user starts dragging the segment.
00234 *************************************************************************/
00235 void ListHeaderSegment::onSegmentDragStart(WindowEventArgs& e)
00236 {
00237         fireEvent(EventSegmentDragStart, e, EventNamespace);
00238 }
00239 
00240 
00241 /*************************************************************************
00242         Handler called when the user stops dragging the segment
00243         (releases mouse button)
00244 *************************************************************************/
00245 void ListHeaderSegment::onSegmentDragStop(WindowEventArgs& e)
00246 {
00247         fireEvent(EventSegmentDragStop, e, EventNamespace);
00248 }
00249 
00250 
00251 /*************************************************************************
00252         Handler called when the drag position changes.
00253 *************************************************************************/
00254 void ListHeaderSegment::onSegmentDragPositionChanged(WindowEventArgs& e)
00255 {
00256         requestRedraw();
00257         fireEvent(EventSegmentDragPositionChanged, e, EventNamespace);
00258 }
00259 
00260 
00261 /*************************************************************************
00262         Handler called when the segment is sized.
00263 *************************************************************************/
00264 void ListHeaderSegment::onSegmentSized(WindowEventArgs& e)
00265 {
00266         requestRedraw();
00267         fireEvent(EventSegmentSized, e, EventNamespace);
00268 }
00269 
00270 
00271 /*************************************************************************
00272         Handler called when the clickable setting for the segment changes
00273 *************************************************************************/
00274 void ListHeaderSegment::onClickableSettingChanged(WindowEventArgs& e)
00275 {
00276         fireEvent(EventClickableSettingChanged, e, EventNamespace);
00277 }
00278 
00279 
00280 /*************************************************************************
00281         Processing for drag-sizing the segment
00282 *************************************************************************/
00283 void ListHeaderSegment::doDragSizing(const Point& local_mouse)
00284 {
00285     float delta = local_mouse.d_x - d_dragPoint.d_x;
00286 
00287     // store this so we can work out how much size actually changed
00288     float orgWidth = getAbsoluteWidth();
00289 
00290     // ensure that we only size to the set constraints.
00291     //
00292     // NB: We are required to do this here due to our virtually unique sizing nature; the
00293     // normal system for limiting the window size is unable to supply the information we
00294     // require for updating our internal state used to manage the dragging, etc.
00295     float maxWidth(d_maxSize.d_x.asAbsolute(System::getSingleton().getRenderer()->getWidth()));
00296     float minWidth(d_minSize.d_x.asAbsolute(System::getSingleton().getRenderer()->getWidth()));
00297     float newWidth = orgWidth + delta;
00298 
00299     if (newWidth > maxWidth)
00300         delta = maxWidth - orgWidth;
00301     else if (newWidth < minWidth)
00302         delta = minWidth - orgWidth;
00303     
00304     // update segment area rect
00305     URect area(d_area.d_min.d_x, d_area.d_min.d_y, d_area.d_max.d_x + UDim(0,PixelAligned(delta)), d_area.d_max.d_y);
00306     setWindowArea_impl(area.d_min, area.getSize());
00307 
00308     // move the dragging point so mouse remains 'attached' to edge of segment
00309     d_dragPoint.d_x += getAbsoluteWidth() - orgWidth;
00310 
00311     WindowEventArgs args(this);
00312     onSegmentSized(args);
00313 }
00314 
00315 
00316 /*************************************************************************
00317         Processing for drag-moving the segment
00318 *************************************************************************/
00319 void ListHeaderSegment::doDragMoving(const Point& local_mouse)
00320 {
00321         // calculate movement deltas.
00322         float   deltaX = local_mouse.d_x - d_dragPoint.d_x;
00323         float   deltaY = local_mouse.d_y - d_dragPoint.d_y;
00324 
00325         // update 'ghost' position
00326         d_dragPosition.d_x += deltaX;
00327         d_dragPosition.d_y += deltaY;
00328 
00329         // update drag point.
00330         d_dragPoint.d_x += deltaX;
00331         d_dragPoint.d_y += deltaY;
00332 
00333         WindowEventArgs args(this);
00334         onSegmentDragPositionChanged(args);
00335 }
00336 
00337 
00338 /*************************************************************************
00339         Initialise and enter the drag moving state.
00340 *************************************************************************/
00341 void ListHeaderSegment::initDragMoving(void)
00342 {
00343         if (d_movingEnabled)
00344         {
00345                 // initialise drag moving state
00346                 d_dragMoving = true;
00347                 d_segmentPushed = false;
00348                 d_segmentHover = false;
00349                 d_dragPosition.d_x = 0.0f;
00350                 d_dragPosition.d_y = 0.0f;
00351 
00352                 // setup new cursor
00353                 MouseCursor::getSingleton().setImage(d_movingMouseCursor);
00354 
00355                 // Trigger the event
00356                 WindowEventArgs args(this);
00357                 onSegmentDragStart(args);
00358         }
00359 
00360 }
00361 
00362 
00363 /*************************************************************************
00364         Initialise the state for hovering over sizing area.
00365 *************************************************************************/
00366 void ListHeaderSegment::initSizingHoverState(void)
00367 {
00368         // only react if settings are changing.
00369         if (!d_splitterHover  && !d_segmentPushed)
00370         {
00371                 d_splitterHover = true;
00372 
00373                 // change the mouse cursor.
00374                 MouseCursor::getSingleton().setImage(d_sizingMouseCursor);
00375 
00376                 // trigger redraw so 'sizing' area can be highlighted if needed.
00377                 requestRedraw();
00378         }
00379 
00380         // reset segment hover as needed.
00381         if (d_segmentHover)
00382         {       
00383                 d_segmentHover = false;
00384                 requestRedraw();
00385         }
00386 
00387 }
00388 
00389 
00390 /*************************************************************************
00391         Initialise the state for hovering over main segment area
00392 *************************************************************************/
00393 void ListHeaderSegment::initSegmentHoverState(void)
00394 {
00395         // reset sizing area hover state if needed.
00396         if (d_splitterHover)
00397         {
00398                 d_splitterHover = false;
00399                 MouseCursor::getSingleton().setImage(getMouseCursor());
00400                 requestRedraw();
00401         }
00402 
00403         // set segment hover state if not already set.
00404         if ((!d_segmentHover) && isClickable())
00405         {
00406                 d_segmentHover = true;
00407                 requestRedraw();
00408         }
00409 }
00410 
00411 
00412 /*************************************************************************
00413         Return true if move threshold for initiating drag-moving has been
00414         exceeded.
00415 *************************************************************************/
00416 bool ListHeaderSegment::isDragMoveThresholdExceeded(const Point& local_mouse)
00417 {
00418         // see if mouse has moved far enough to start move operation
00419         // calculate movement deltas.
00420         float   deltaX = local_mouse.d_x - d_dragPoint.d_x;
00421         float   deltaY = local_mouse.d_y - d_dragPoint.d_y;
00422 
00423         if ((deltaX > SegmentMoveThreshold) || (deltaX < -SegmentMoveThreshold) ||
00424                 (deltaY > SegmentMoveThreshold) || (deltaY < -SegmentMoveThreshold))
00425         {
00426                 return true;
00427         }
00428         else
00429         {
00430                 return false;
00431         }
00432 
00433 }
00434 
00435 
00436 /*************************************************************************
00437         Handler for when mouse position changes in widget area (or captured)
00438 *************************************************************************/
00439 void ListHeaderSegment::onMouseMove(MouseEventArgs& e)
00440 {
00441         // base class processing
00442         Window::onMouseMove(e);
00443 
00444         //
00445         // convert mouse position to something local
00446         //
00447         Point localMousePos(screenToWindow(e.position));
00448 
00449         if (getMetricsMode() == Relative)
00450         {
00451                 localMousePos = relativeToAbsolute(localMousePos);
00452         }
00453 
00454         // handle drag sizing
00455         if (d_dragSizing)
00456         {
00457                 doDragSizing(localMousePos);
00458         }
00459         // handle drag moving
00460         else if (d_dragMoving)
00461         {
00462                 doDragMoving(localMousePos);
00463         }
00464         // not sizing, is mouse in the widget area?
00465         else if (isHit(e.position))
00466         {
00467                 // mouse in sizing area & sizing is enabled
00468                 if ((localMousePos.d_x > (getAbsoluteWidth() - d_splitterSize)) && d_sizingEnabled)
00469                 {
00470                         initSizingHoverState();
00471                 }
00472                 // mouse not in sizing area and/or sizing not enabled
00473                 else
00474                 {
00475                         initSegmentHoverState();
00476 
00477                         // if we are pushed but not yet drag moving
00478                         if (d_segmentPushed && !d_dragMoving)
00479                         {
00480                                 if (isDragMoveThresholdExceeded(localMousePos))
00481                                 {
00482                                         initDragMoving();
00483                                 }
00484 
00485                         }
00486 
00487                 }
00488 
00489         }
00490         // mouse is no longer within the widget area...
00491         else
00492         {
00493                 // only change settings if change is required
00494                 if (d_splitterHover)
00495                 {
00496                         d_splitterHover = false;
00497                         MouseCursor::getSingleton().setImage(getMouseCursor());
00498                         requestRedraw();
00499                 }
00500 
00501                 // reset segment hover state if not already done.
00502                 if (d_segmentHover)
00503                 {       
00504                         d_segmentHover = false;
00505                         requestRedraw();
00506                 }
00507 
00508         }
00509 
00510         e.handled = true;
00511 }
00512 
00513 
00514 /*************************************************************************
00515         Handler for when mouse buttons are pushed
00516 *************************************************************************/
00517 void ListHeaderSegment::onMouseButtonDown(MouseEventArgs& e)
00518 {
00519         // base class processing
00520         Window::onMouseButtonDown(e);
00521 
00522         if (e.button == LeftButton)
00523         {
00524                 // ensure all inputs come to us for now
00525                 if (captureInput())
00526                 {
00527                         // get position of mouse as co-ordinates local to this window.
00528                         Point localPos(screenToWindow(e.position));
00529 
00530                         if (getMetricsMode() == Relative)
00531                         {
00532                                 localPos = relativeToAbsolute(localPos);
00533                         }
00534 
00535                         // store drag point for possible sizing or moving operation.
00536                         d_dragPoint = localPos;
00537 
00538                         // if the mouse is in the sizing area
00539                         if (d_splitterHover)
00540                         {
00541                                 if (isSizingEnabled())
00542                                 {
00543                                         // setup the 'dragging' state variables
00544                                         d_dragSizing = true;
00545                                 }
00546 
00547                         }
00548                         else
00549                         {
00550                                 d_segmentPushed = true;
00551                         }
00552 
00553                 }
00554 
00555                 e.handled = true;
00556         }
00557 
00558 }
00559 
00560 
00561 /*************************************************************************
00562         Handler for when mouse buttons area released
00563 *************************************************************************/
00564 void ListHeaderSegment::onMouseButtonUp(MouseEventArgs& e)
00565 {
00566         // base class processing
00567         Window::onMouseButtonUp(e);
00568 
00569         if (e.button == LeftButton)
00570         {
00571                 // if we were pushed and mouse was released within our segment area
00572                 if (d_segmentPushed && d_segmentHover)
00573                 {
00574                         WindowEventArgs args(this);
00575                         onSegmentClicked(args);
00576                 }
00577                 else if (d_dragMoving)
00578                 {
00579                         MouseCursor::getSingleton().setImage(getMouseCursor());
00580                         
00581                         WindowEventArgs args(this);
00582                         onSegmentDragStop(args);
00583                 }
00584 
00585                 // release our capture on the input data
00586                 releaseInput();
00587                 e.handled = true;
00588         }
00589 
00590 }
00591 
00592 
00593 /*************************************************************************
00594         Handler for when a mouse button is double-clicked
00595 *************************************************************************/
00596 void ListHeaderSegment::onMouseDoubleClicked(MouseEventArgs& e)
00597 {
00598         // base class processing
00599         Window::onMouseDoubleClicked(e);
00600 
00601         // if double-clicked on splitter / sizing area
00602         if ((e.button == LeftButton) && d_splitterHover)
00603         {
00604                 WindowEventArgs args(this);
00605                 onSplitterDoubleClicked(args);
00606 
00607                 e.handled = true;
00608         }
00609 
00610 }
00611 
00612 
00613 /*************************************************************************
00614         Handler for when mouse leaves the widget area (uncaptured)
00615 *************************************************************************/
00616 void ListHeaderSegment::onMouseLeaves(MouseEventArgs& e)
00617 {
00618         // base class processing
00619         Window::onMouseLeaves(e);
00620 
00621         d_splitterHover = false;
00622         d_dragSizing = false;
00623         d_segmentHover = false;
00624         requestRedraw();
00625 }
00626 
00627 
00628 /*************************************************************************
00629         Handler for when mouse input capture is lost
00630 *************************************************************************/
00631 void ListHeaderSegment::onCaptureLost(WindowEventArgs& e)
00632 {
00633         // base class processing
00634         Window::onCaptureLost(e);
00635 
00636         // reset segment state
00637         d_dragSizing = false;
00638         d_segmentPushed = false;
00639         d_dragMoving = false;
00640 
00641         e.handled = true;
00642 }
00643 
00644 /*************************************************************************
00645         adds properties for the class
00646 *************************************************************************/
00647 void ListHeaderSegment::addHeaderSegmentProperties(void)
00648 {
00649         addProperty(&d_clickableProperty);
00650         addProperty(&d_sizableProperty);
00651         addProperty(&d_dragableProperty);
00652         addProperty(&d_sortDirectionProperty);
00653 }
00654 
00655 
00656 
00657 } // End of  CEGUI namespace section

Generated on Wed Sep 7 09:56:32 2005 for Crazy Eddies GUI System by  doxygen 1.4.3