00001 //# DisplayData.h: base class for display objects 00002 //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id$ 00027 00028 #ifndef TRIALDISPLAY_DISPLAYDATA_H 00029 #define TRIALDISPLAY_DISPLAYDATA_H 00030 00031 #include <casa/aips.h> 00032 #include <casa/Arrays/Vector.h> 00033 #include <casa/Arrays/Matrix.h> 00034 #include <casa/Containers/List.h> 00035 #include <coordinates/Coordinates/CoordinateSystem.h> 00036 #include <display/Utilities/DisplayOptions.h> 00037 #include <display/Display/WorldCanvasHolder.h> 00038 #include <display/Display/AttValBase.h> 00039 #include <display/DisplayEvents/DisplayEH.h> 00040 00041 namespace casa { //# NAMESPACE CASA - BEGIN 00042 00043 class Attribute; 00044 class AttributeBuffer; 00045 class Unit; 00046 class WorldCanvas; 00047 class Colormap; 00048 class String; 00049 class WCPositionEH; 00050 class WCMotionEH; 00051 class WCRefreshEH; 00052 class WCPositionEvent; 00053 class WCMotionEvent; 00054 class WCRefreshEvent; 00055 class Record; 00056 00057 // <summary> 00058 // Base class for display objects. 00059 // </summary> 00060 // 00061 // <use visibility=export> 00062 // 00063 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos=""> 00064 // </reviewed> 00065 // 00066 // <prerequisite> 00067 // <li> WorldCanvas 00068 // <li> WorldCanvasHolder 00069 // <li> Attribute 00070 // <li> AttributBuffer 00071 // </prerequisite> 00072 // 00073 // <etymology> 00074 // A class having "DisplayData" as its base is used to generate 00075 // "Display"s out of "Data." 00076 // </etymology> 00077 // 00078 // <synopsis> The basic drawing devices in the Display Library are the 00079 // PixelCanvas and the WorldCanvas. These devices know nothing about what real 00080 // data look like, what kind of object will draw on these devices and in what 00081 // kind of circumstances these devices will be used. The only thing they 00082 // define is the interface of how to draw on them and the way they communicate 00083 // with other objects (the event handlers). Building in no assumptions in the 00084 // Canvases on how they will be used should give larger flexibility in how one 00085 // can actually use these Canvases. Since the Canvases know nothing about how 00086 // real data looks, a class is needed to transform data into objects the 00087 // Canvases do understand. These are the DisplayData. A DisplayData generates, 00088 // based on data and some algorithm to represent that data, a number of 00089 // primitives that it draws on the WorldCanvas. So in a way, 'the data draw 00090 // themselves'. The definition of how data is represented (image, contour, 00091 // rendering, list of symbols from a catalogue, etc, etc) is entirely defined 00092 // by these DisplayData and as long it can be done using the primitives of the 00093 // WorldCanvas, there are no restrictions. If one finds a new way of 00094 // representing data, the only thing one has to do is to write a new 00095 // DisplayData that generates this representation and draws it on the 00096 // WorldCanvas using the primitives of the WorldCnvas. 00097 // 00098 // To do the administration of a number of DisplayDatas on one WorldCanvas, a 00099 // bookkeeping class is needed, this is the WorldCnvasHolder. 00100 // 00101 // Some DisplayData will consist of a sequence of display object (eg a set of 00102 // channels in a data cube). The DisplayData are build with sequences in mind 00103 // (as is clear from the interface), and the Display Library is designed very 00104 // strongly with movies in mind. The programmer is free to define what a 00105 // sequence really means, but it is probably best to keep the structure of the 00106 // sequence in a DisplayData fairly logical. But there is not requirement on 00107 // the structure of the sequence. 00108 // 00109 // Before a display object is displayed (ie when a refresh happens), a size 00110 // control step is performed. The WorldCanvas call a sizeControl event 00111 // handler. Normally this will be a handler that is installed by the 00112 // WorldCanvasHolder. All the WorldCanvasHolder does is to call the 00113 // sizeControl member function of all displayData registered with the 00114 // WorldCanvasHolder to do the sizeControl. The purpose of the size control is 00115 // to put the WorldCanvas in a correct state before the objects are actually 00116 // drawn. For example, for images there can be restrictions on the size of the 00117 // output array (eg the image is expanded using pixelreplication which means 00118 // that the draw area of the WorldCanvas must by an integral of the size of 00119 // the image). For each DisplayData the WorldCanvasHolder calls the sizeControl 00120 // function, supplying an AttributeBuffer where the DisplayData should set the 00121 // Attributes it needs to be set. THERE IS ONE IMPORTANT RULE IN THIS: a 00122 // DisplayData should never overwrite an Attribute that is already set in this 00123 // buffer. If the WorldCanvas cannot be put in a correct state during the size 00124 // control, a DisplayData should turn itself off. DisplayData are also 00125 // responsible for the linear coordinate system of the WorldCanvas and usually 00126 // setting that up will be done in this step. 00127 00128 00129 // (dk 6/04 note on 'size control'). The important WC state set during 00130 // sizeControl() defines a series of coordinate transformations, ultimately 00131 // between screen (PixelCanvas) pixels and coordinates in world space. 00132 // First, there are the limits of the WC's 'draw area', inside the labelling 00133 // margins, on the PC ('canvasDraw{X,Y}{Size,Offset}' WC Attributes). 00134 // Second is the 'zoom window': the area of 'linear coordinate' space 00135 // currently mapped to the draw area ('lin{X,Y}{Min,Max}' WC Attributes). 00136 // Also stored in linear terms are the maximum extents of the data 00137 // ('lin{X,Y}{Min,Max}Limit' Attributes), which are used to set the zoom 00138 // window initially or when 'unzoom' (zoom-to-extent) is requested. 00139 // 00140 // 'Linear coordinates' often correspond to indices within the data 00141 // being displayed, although in principle this is not necessary. They 00142 // serve to isolate the simple linear scaling/translation (zoom and pan) 00143 // transformations from the final transformation (often a nonlinear sky 00144 // projection) between 'linear coordinates' and world space (which is 00145 // changed less often). 00146 // 00147 // (Also, linear coordinates define an entire plane, although a given 00148 // sky-coordinate projection to that plane may not be defined everywhere. 00149 // Keeping zoom windows defined in linear coordinates allows natural 00150 // display of all-sky images even when sky coordinates are not defined 00151 // everywhere in the display area. In other words, the existing 00152 // scheme allows all-sky images to be displayed easily _in principle_; 00153 // it does not work currently due to inappropriate insistence of 00154 // WC::drawImage() that its draw area be given in world coordinates; 00155 // this is high on the list of bugfix priorities...). 00156 // 00157 // The final transformation makes use of the Coordinate classes (which 00158 // ultimately use wcslib for any needed sky projection). It defines the 00159 // current 2D surface on display within some nD world space, as parameterized 00160 // by the X and Y linear coordinates. State for this purpose includes the 00161 // 'WorldCanvas CoordinateSystem' or 'WCCS' (WorldCanvas::itsCoordinateSystem) 00162 // plus 'axis codes' (which have the odd Attribute names 00163 // '{x,y}axiscode (required match)'). They are intended to define the 00164 // coordinate values and types for the world space currently of interest. 00165 // 00166 // This latter transformation is not as simple or well-defined as it might 00167 // appear, however (and in my opinion this area still needs work). First of 00168 // all, the WCCS is a rather late addition to WC interface, and in most cases 00169 // is _not even used_ to do WC linear-to-world transformations. Instead, this 00170 // chore is handed off (via the older WCCoordinateHandler interface) to one 00171 // of the DDs currently registered on WC's companion object, WorldCanvasHolder. 00172 // Also, the axis codes do not always provide enough information about the 00173 // current world space for DDs to determine whether they are designed to 00174 // draw in that space (which, in my opinion, should be the codes' purpose). 00175 // They also implicitly assume a 1-to-1 correspondence between linear and 00176 // world coordinates, which is not very general. 00177 // 00178 // Back to how it works now, though. During the 'sizeControl' step of 00179 // refresh, the WCH will attempt to determine a 'CS master DD'. (Usually the 00180 // same DD will remain 'in charge' as long as it is registered). Within 00181 // the sizeControl routine, DDs should test isCSMaster(wch) to determine 00182 // whether they have permission to become the CS master. If so, and if they 00183 // are willing and able to become CS master, they must set all of the WC 00184 // state above and return True; in all other cases they should return False. 00185 // Only the CSmaster should set the WC CS or axis codes, and it will be 00186 // responsible for performing the WC's linToWorld, etc. transformation chores. 00187 // In other words, it is entirely in charge of the final transformation to 00188 // world coordinates. In principle, other DDs may perform certain 'slave 00189 // sizeControl' tweaks (such as aligning the zoom window on data pixel 00190 // boundaries or redefining maximum zoom extents). No current implementations 00191 // do anything but return False if they are not the master, however. 00192 // 00193 // Major implementation examples for sizeControl() can be found in the 00194 // ActiveCaching2dDD and PrincipalAxesDD classes. They should be consulted 00195 // as well for the conventions for processing WC 'zoom/unzoom' order 00196 // attributes, another CSmaster responsibility. (<\dk>) 00197 00198 00199 00200 // The control of what is displayed in a display application is done with 00201 // setting restrictions on the WorldCanvasHolder (and possibly on the 00202 // Displaydata). Restrictions are implemented as Attributes and stored in 00203 // AttributeBuffers. To define what is displayed, one sets one or more 00204 // restrictions on the WorldCanvasHolder and calls a refresh on the 00205 // WorldCanvas. Most DisplayData will have pre-defined restrictions, for 00206 // example in an ImageDisplayData each image has defined the restriction 00207 // zIndex (set to the pixelindex of the 'third' axis in the data set) and 00208 // zValue (set to the 'third' worldcoordinate of the image). So to display 00209 // channel 13 of a data cube, one only has to set on the WorldCanvasHolder a 00210 // restriction called zIndex with value 13 and call refresh: 00211 // 00212 // <srcblock> 00213 // worldCanvasHolder.setRestriction("zIndex", 13); 00214 // worldCanvas.refresh(); 00215 // </srcblock> 00216 // 00217 // Movies can be made using the Animator class. One way it to use indices, but 00218 // there is a generic way of defining movies using restrictions. So a sequence 00219 // does not have to correspond to a 'logical' or 'physical' sequence in some 00220 // datastructure (channels in a cube for example), but can be made of images 00221 // from different datasets (e.g. blinking) and display data in different 00222 // forms. This system is very flexible and there are no real limits to what a 00223 // movie really means. 00224 // 00225 // The DisplayData also define the coordinate system of the WorldCanvas. If 00226 // the WorldCanvas has to do a coordinate transformation, it asks a coordinate 00227 // handler to do this. When a WorldCanvasHolder is created for a WorldCanvas, 00228 // the WorldCanvasHolder install a coordinate handler on the WorldCanvas. What 00229 // this coordinate handlers does is to ask the DisplayData that is first in 00230 // the list of the WorldcanvasHolder to do the transformation. This is quite 00231 // an indirect way of doing the transformation, but it is very flexible (and 00232 // the WorldCanvas does not have to know what an Aips++ coordinate system is, 00233 // or what a DisplayData is, , which makes the WorldCanvas more generic). Most 00234 // DisplayData will use the coordinate system of the data belonging to this 00235 // DisplayData to do the transformation, but this is not a requirement. As 00236 // long as you produce something that can be used as a coordinate system, it 00237 // does not matter how you compute it. The most important thing is that the 00238 // DisplayData are responsible for this. At the moment, only the Vector 00239 // version should be implemented, since efficient transformation of a series 00240 // of positions is not available in AIPS++. The Matrix versions are handled at 00241 // the WorldCanvas level at the moment. Most DisplayData will assume that the 00242 // linear coordinate system of the WorldCanvas corresponds to some underlying 00243 // pixel array. The way the linear coordinate system is used is that it is the 00244 // input for the coordinate transformation to world coordinates. The 00245 // DisplayData are responsible for keeping the linear system correct. 00246 00247 // Other event handlers that the DisplayData have to implement are the 00248 // position- and the motion event handlers. (PositionEH and MotionEH). These 00249 // are called by the WorldCanvasHolder in response to an event on the 00250 // WorldCanvas. It is up to the DisplayData what to do with these events. 00251 // 00252 // One can also register position- and motion event handlers on a 00253 // DisplayData. What kind of event a DisplayData generates in response to an 00254 // event on the WorldCanvas (passed to the DisplayData by the 00255 // WorldCanvasHolder by calling PositionEH/MotionEH) is entirely up to the 00256 // DisplayData, as long as the handlers are derived from WCPositionEH or 00257 // WCMotionEH. One can also install a refresh handler on a DisplayData, 00258 // although I have not thought of any use for that (but allowed for it to keep 00259 // symmetry with the other events). 00260 // 00261 // (1/02) DisplayEH interface has also been added for handling generic 00262 // DisplayEvents through handleEvent(). It is expected that DDs will handle 00263 // these events themselves, as needed, or pass them on in an ad-hoc manner. 00264 // However, nothing prevents implementing a dispatching list for passing 00265 // on these events too, if needed. 00266 // 00267 // (3/03) One can also register itself as a DisplayEventHandler on a 00268 // DisplayData. The handleEvent function of DisplayEH is implemented 00269 // to forward any DisplayEvents its receives to these 00270 // handlers. Therefore, all DisplayDatas that overide the handleEvent 00271 // function, should call the handleEvent function of its super class 00272 // so this forwarding can take place. 00273 // 00274 // A DisplayData also has to implement a refreshEH. This function is called by 00275 // the WorldCanvasHolder in response to a refresh request of the WorldCanvas. 00276 // This is a very important function: here the actual drawing has 00277 // to happen, using the draw primitives of the WorldCanvas. It is a good idea 00278 // to check the state of the WorldCanvas before the draw is actually done, and 00279 // decide not to draw if the state (for whatever reason) is not ok. Also be 00280 // aware that it is a requirement that one DisplayData can work for more than 00281 // one WorldCanvasHolders at a time, so the DisplayData has to do some 00282 // administration for that (which WorldCanvasHolders am I working for and 00283 // which one am I drawing on at the moment, things like that). See 00284 // ImageDisplayData for an example of that. 00285 // 00286 // DisplayData also have Attributes. These can be used to store whatever 00287 // information on a DisplayData. The Attributes give a standard interface to 00288 // do this. 00289 // </synopsis> 00290 // 00291 // <example> 00292 // <srcBlock> 00293 // </srcBlock> 00294 // </example> 00295 // 00296 00297 // <motivation> 00298 // An abstract interface between data and canvases was needed 00299 //</motivation> 00300 // 00301 // <todo> 00302 // 00303 // <li> When efficient implementations of the Matrix versions of the 00304 // coordinate transformations become available in AIPS++, these should be 00305 // implemented in DisplayData 00306 // 00307 // </todo> 00308 // 00309 00310 class DisplayData : public DisplayOptions, public DisplayEH { 00311 00312 public: 00313 00314 // (Required) default constructor. 00315 DisplayData(); 00316 00317 // required destructor 00318 virtual ~DisplayData(); 00319 00320 // Coordinate transformations, called by WorldCanvasHolder (Matrix versions 00321 // not implemented) 00322 virtual Bool linToWorld(Vector<Double>& world, 00323 const Vector<Double>& lin) = 0; 00324 virtual Bool worldToLin(Vector<Double>& lin, 00325 const Vector<Double>& world) = 0; 00326 00327 // Format a string containing coordinate information at 00328 // the given world coordinate 00329 virtual String showPosition(const Vector<Double> &world, 00330 const Bool &displayAxesOnly = False) = 0; 00331 00332 // Format a string containing value information at the 00333 // given world coordinate 00334 virtual String showValue(const Vector<Double> &world) = 0; 00335 00336 00337 00338 // Some routines that give info on the axes names, units etc. I am not sure 00339 // this is the right way of doing it. Specifically I am not sure 00340 // <src>dataUnit</src> belongs in this list (data units may not make sense 00341 // for some kinds of DisplayData...). 00342 // <group> 00343 virtual Vector<String> worldAxisNames() = 0; 00344 virtual Vector<String> worldAxisUnits() = 0; 00345 virtual const Unit dataUnit() = 0; 00346 // </group> 00347 00348 // Returns the number of elements in this DisplayData (mainly for movie 00349 // purposes). First one is no. of elements for specific WCanvas. 00350 virtual const uInt nelements(const WorldCanvasHolder &wcHolder) const = 0; 00351 // and non-specific 00352 virtual const uInt nelements() const = 0; 00353 00354 // Add general restrictions or a restriction for item <src>itemNum</src> of 00355 // this DisplayData. Note that the item versions of the restriction 00356 // interface are not implemented. I am not sure the item versions belong in 00357 // DisplayData and instead they should only appear in some derived classes. 00358 // <group> 00359 virtual void addRestrictions(AttributeBuffer& otherBuf); 00360 virtual void addRestriction(Attribute& newRestriction, Bool permanent); 00361 virtual void addElementRestrictions(const uInt itemNum, 00362 AttributeBuffer& other); 00363 virtual void addElementRestriction(const uInt itemNum, 00364 Attribute& newRestriction, 00365 Bool permanent); 00366 // </group> 00367 00368 // Set general restrictions or a restriction for item <src>itemNum</src> of 00369 // this DisplayData. Note that the item versions of the restriction 00370 // interface are not implemented. 00371 // <group> 00372 virtual void setRestrictions(AttributeBuffer& otherBuf); 00373 virtual void setRestriction(Attribute& newRestriction); 00374 virtual void setElementRestrictions(const uInt itemNum, 00375 AttributeBuffer& other); 00376 virtual void setElementRestriction(const uInt itemNum, 00377 Attribute& newRestriction); 00378 // </group> 00379 00380 // Remove a general restriction or a restriction from item <src>itemNum</src> 00381 // <group> 00382 virtual void removeRestriction(const String& name); 00383 virtual void removeElementRestriction(const uInt itemNum, 00384 const String& name); 00385 // </group> 00386 00387 // Clear all general restrictions or all restrictions of item 00388 // <src>itemNum</src> (except the ones that are permanent of course...) 00389 // <group> 00390 virtual void clearRestrictions(); 00391 virtual void clearElementRestrictions(const uInt itemNum); 00392 // </group> 00393 00394 // Check if a general restriction or a restriction for item 00395 // <src>itemNum</src> with name <src>name</src> exists. 00396 // <group> 00397 virtual Bool existRestriction(const String& name); 00398 virtual Bool existElementRestriction(const uInt itemNum, 00399 const String& name); 00400 // </group> 00401 00402 // Get a handle to the buffer of general restrictions or of the buffer of 00403 // restrictions for item <src>itemNum</src> 00404 // <group> 00405 virtual AttributeBuffer *restrictionBuffer(); 00406 virtual AttributeBuffer *elementRestrictionBuffer(const uInt itemNum); 00407 // </group> 00408 00409 00410 // Check whether the DD is is compatible with all WC[H] 00411 // state, including its coordinate state, restrictions, and zIndex (if any). 00412 // It also assures that the DD is 'focused' on this WC[H] and its zindex 00413 // for purposes of drawing or event handling. 00414 // <group> 00415 virtual Bool conformsTo(const WorldCanvas *wCanvas) { 00416 WorldCanvasHolder *wch = findHolder(wCanvas); 00417 rstrsConformed_ = csConformed_ = zIndexConformed_ = False; 00418 return (wch!=0 && conformsTo(*wch)); } 00419 00420 virtual Bool conformsTo(const WorldCanvasHolder& wch) { 00421 conformsToRstrs(wch); 00422 conformsToCS(wch); 00423 conformsToZIndex(wch); 00424 return conformed(); } 00425 // </group> 00426 00427 // Determine whether DD restrictions are in conformance with restrictions 00428 // on the given WCH. (Note: this will include blink index, if any, 00429 // but _not_ zIndex. zIndex is an individual DM restriction, not an 00430 // overall DD restriction). 00431 virtual Bool conformsToRstrs(const WorldCanvasHolder& wch) { 00432 rstrsConformed_ = wch.matchesRestrictions(restrictions); 00433 return rstrsConformed_; } 00434 00435 // Determine whether DD is compatible with the WC[H]'s current 00436 // world coordinates. Derived DDs can override according to their 00437 // individual capabilities (PADD and ACDD match axis codes). 00438 // Overriding DDs should set csConformed_ to the value returned. 00439 virtual Bool conformsToCS(const WorldCanvasHolder& wch) { 00440 csConformed_ = True; 00441 return csConformed_; } 00442 00443 // Determine whether DD is compatible with the current canvas 00444 // animation (zIndex) position. (This usually means that it lies 00445 // within the current number of DD animation frames). 00446 // (Generally, DDs should probably override setActiveZIndex_() 00447 // rather than this method). 00448 virtual Bool conformsToZIndex(const WorldCanvasHolder& wch) { 00449 Int zindex = 0; // (default in case no zIndex exists). 00450 const AttributeBuffer *rstrs = wch.restrictionBuffer(); 00451 if (rstrs->exists("zIndex")) rstrs->getValue("zIndex",zindex); 00452 return setActiveZIndex_(zindex); } 00453 00454 // Retrieve 'Active' zIndex. Not likely to be meaningful/useful 00455 // unless conformsTo(wch) (or conformsToZIndex(wch)) has been called 00456 // just prior (and has returned a True result). Those calls make 00457 // wch the 'active' one; zIndex varies from one wch to another. 00458 // You can pass a wch, which will force a call to conformsToZIndex(wch). 00459 virtual Int activeZIndex(const WorldCanvasHolder* wch=0) { 00460 if(wch!=0) conformsToZIndex(*wch); 00461 return activeZIndex_; } 00462 00463 00464 00465 // Set firstZIndex to minimum zIndex setting from all canvases where 00466 // this DD is registered. (In the usual case where the DD is registered 00467 // on one [multi]panel, this will return its animator 'frame #' setting). 00468 // The routine will return false (and firstZIndex remain unchanged) if 00469 // there are no registered canvases with zIndex below axZrng--the total 00470 // number of frames on the Z axis. axZrng can be supplied; the default 00471 // means 'use nelements()'. 00472 // (Note: to get the zindex from the 'currently active' wch instead, 00473 // a DD should check activeZIndex_. Or, if the desired wch is known, 00474 // it can retrieve the zIndex itself from wch.restrictionBuffer()). 00475 virtual Bool getFirstZIndex(int& firstZIndex, Int axZrng=-1) const { 00476 Block<Int> zInds = allZIndices(axZrng); 00477 if(zInds.nelements()==0) return False; 00478 firstZIndex=zInds[0]; return True; } 00479 00480 00481 00482 // Add event handlers on the DisplayData. I am not sure there is also a need 00483 // for a refresh handler on a DisplayData, but allowing for it makes 00484 // things 'symmetric'. These member functions throw an AipsError if a null 00485 // pointer is passed. 00486 // <group> 00487 virtual void addPositionEventHandler(WCPositionEH *positionHandler); 00488 virtual void addMotionEventHandler(WCMotionEH *motionHandler); 00489 virtual void addRefreshEventHandler(WCRefreshEH *refreshHandler); 00490 virtual void addDisplayEventHandler(DisplayEH *displayHandler); 00491 // </group> 00492 00493 // Remove eventhandlers 00494 // <group> 00495 virtual void removePositionEventHandler(WCPositionEH& positionHandler); 00496 virtual void removeMotionEventHandler(WCMotionEH& motionHandler); 00497 virtual void removeRefreshEventHandler(WCRefreshEH& refreshHandler); 00498 virtual void removeDisplayEventHandler(DisplayEH& displayHandler); 00499 // </group> 00500 00501 // Set/remove/get a ColourMap (sorry, ColorMap) for this DisplayData 00502 // setColormap() throw an AipsError is a null pointer is passed. colormap() 00503 // returns 0 if no Colormap is registered. 00504 // <group> 00505 virtual void setColormap(Colormap *cmap, Float weight); 00506 virtual void removeColormap(); 00507 virtual Colormap *colormap() const 00508 { return itsColormap; } 00509 // </group> 00510 00511 00512 // set an Attribute or Attributes 00513 // <group> 00514 void setAttribute(Attribute& at); 00515 void setAttributes(AttributeBuffer& at); 00516 // </group> 00517 00518 // User interface to get value from the attribute buffer 00519 // <group> 00520 00521 Bool getAttributeValue(const String& name, uInt& newValue) ; 00522 Bool getAttributeValue(const String& name, Int& newValue) ; 00523 Bool getAttributeValue(const String& name, Float& newValue) ; 00524 Bool getAttributeValue(const String& name, Double& newValue) ; 00525 Bool getAttributeValue(const String& name, Bool& newValue) ; 00526 Bool getAttributeValue(const String& name, String& newValue) ; 00527 Bool getAttributeValue(const String& name, Vector<uInt>& newValue) ; 00528 Bool getAttributeValue(const String& name, Vector<Int>& newValue) ; 00529 Bool getAttributeValue(const String& name, Vector<Float>& newValue) ; 00530 Bool getAttributeValue(const String& name, Vector<Double>& newValue) ; 00531 Bool getAttributeValue(const String& name, Vector<Bool>& newValue) ; 00532 Bool getAttributeValue(const String& name, Vector<String>& newValue) ; 00533 // </group> 00534 00535 // Check if a certain Attribute exists 00536 Bool existsAttribute(String& name) ; 00537 00538 // Remove an Attribute 00539 void removeAttribute(String& name); 00540 00541 // Get the type of the Attribute 00542 AttValue::ValueType attributeType(String& name) ; 00543 00544 // Set an attribute on any WorldCanvas for which this DD is CS master 00545 void setAttributeOnPrimaryWCHs(Attribute &at); 00546 00547 // <group> 00548 virtual void notifyRegister(WorldCanvasHolder *wcHolder) ; 00549 // <src>ignoreRefresh</src> tells the DD not to refresh just to clean 00550 // up DMs 00551 virtual void notifyUnregister(WorldCanvasHolder& wcHolder, 00552 Bool ignoreRefresh = False) ; 00553 // </group> 00554 00555 // remove this DD everywhere--will stop any more refresh handling by 00556 // the DD. It is a good idea for top-level DDs to call this first 00557 // in their destructor. 00558 virtual void removeFromAllWCHs(); 00559 00560 // install the default options for this DisplayData 00561 virtual void setDefaultOptions(); 00562 00563 // apply options stored in val to the DisplayData; return value 00564 // True means a refresh is needed... 00565 virtual Bool setOptions(Record &rec, Record &recOut); 00566 00567 // retrieve the current and default options and parameter types. 00568 virtual Record getOptions(); 00569 00570 // an explicit refresh: should be called if the DisplayData is 00571 // changed such that drawing is required. If clean is True, 00572 // the DD is totally rebuilt, in practice. This is provided 00573 // for higher level control, even explicit control of refresh 00574 // where necessary. 00575 virtual void refresh(Bool clean = False); 00576 00577 // an explicit request to draw the axes and/or labels. Returns 00578 // True if axes were drawn, otherwise False; 00579 virtual Bool labelAxes(const WCRefreshEvent &ev); 00580 00581 // Return the class name of this DisplayData; useful mostly for 00582 // debugging purposes, and perhaps future use in the glish widget 00583 // interface. 00584 virtual String className() { return String("DisplayData"); } 00585 00586 // Return the DisplayData type; used by the WorldCanvasHolder to 00587 // determine the order of drawing. 00588 virtual Display::DisplayDataType classType() = 0; 00589 00590 // Identify the WorldCanvasHolder for the given WorldCanvas. Return 00591 // <src>0</src> if the DisplayData does not know of a 00592 // WorldCanvasHolder for the WorldCanvas. 00593 virtual WorldCanvasHolder *findHolder(const WorldCanvas *wCanvas); 00594 00595 // Return a sorted Block of all animation frame numbers currently set 00596 // onto all WCHs where this DD is registered. 00597 // The frame numbers returned are guaranteed to be in the range 00598 // 0 <= zIndex < axZrng, where axZrng is the total number of frames 00599 // on the Z axis. axZrng can be supplied; the default is nelements(). 00600 virtual Block<Int> allZIndices(Int axZrng=-1) const; 00601 00602 // Will be called just before registering the [GTk]DD on a [GTk]PanelDisplay 00603 // which has none registered on it yet. The DD can set the initial 00604 // animator position in this case by overriding this method to set 00605 // preferredZIndex and return True. 00606 virtual Bool zIndexHint(Int& preferredZIndex) const { return False; } 00607 00608 // Overide DisplayEH::handleEvent. This base class on forwards the 00609 // event on to listeners 00610 virtual void handleEvent(DisplayEvent &ev); 00611 00612 // Is this DD the CS master of the passed WCH? 00613 // Defaulting wch to 0 asks whether this DD is CS master of _some_ WCH 00614 // on which it is registered. (That option is mostly a kludge, since the 00615 // DD may be CS master of some WCHs and not others). 00616 virtual Bool isCSmaster(const WorldCanvasHolder* wch=0) const; 00617 00618 // DD 'Absolute Pixel Coordinates', e.g. channel numbers, are internally 00619 // 0-based (they begin numbering at 0), but certain external user-interface 00620 // functions (e.g. showPosition(), used for position tracking) have 00621 // produced 1-based output traditionally for the glish-based viewer. 00622 // uiBase_, and related methods uiBase() and setUIBase(), allow newer 00623 // (python/Qt-based) code to cause external ui functions like showValue() 00624 // to report 0-based values instead. Unless setUIBase(0) is called, the 00625 // traditional 1-based reporting behavior is retained by default. 00626 // 00627 // If you are using 0-basing in the user interface, you should call 00628 // setUIBase(0) right after constructing this DD, before other 00629 // user interface operations such as getOptions(). 00630 // <group> 00631 virtual Int uiBase() { return uiBase_; } 00632 00633 virtual void setUIBase(Int uibase) { 00634 if(uibase==0 || uibase==1) uiBase_ = uibase; } 00635 // </group> 00636 00637 00638 protected: 00639 00640 // DDs may override to adjust the internal stored current animation 00641 // index (activeZIndex_) if necessary, and to set return value False 00642 // iff the passed zindex won't work for the DD. zIndexConformed_ 00643 // should be set to the value returned; activeZIndex_ should also 00644 // be set appropriately. 00645 virtual Bool setActiveZIndex_(Int zindex) { 00646 activeZIndex_ = zindex; 00647 zIndexConformed_ = True; 00648 return zIndexConformed_; } 00649 00650 00651 // The Book says that we should not put data members in class that is 00652 // supposed to only define an interface, but by putting these here, we can 00653 // implement some of the restriction & eventhandling stuff so that people do 00654 // not have to repeat it. 00655 00656 // buffer for storing restrictions 00657 AttributeBuffer restrictions; 00658 00659 // buffer for storing Attributes 00660 AttributeBuffer attributes; 00661 00662 // list of DisplayDataElements, which are of type DisplayMethod or derived 00663 PtrBlock<void *> DDelement; 00664 00665 // Protected interface for WorldCanvasHolder, can be called by the friends 00666 // of DisplayData, but are nobody else's business. I decided to do this in 00667 // this way to avoid that the programmer has to both register the 00668 // DisplayData with the WorldCanvasHolder AND the WorldCanvasHolder with the 00669 // DisplayData. Now one of the two is done automatically. 00670 // The WorldCanvasHolder is my friend. This is to hide the eventhandler 00671 // interfaces listed below from the outside world. The WorldCanvasHolder is 00672 // the only class that needs them 00673 friend class WorldCanvasHolder; 00674 00675 // Indicates the 'current' animation frame, i.e. the zIndex on the canvas 00676 // for which confromsTo(wch) was last called. Intended to be set only 00677 // by setActiveZIndex_() in this class or derived classes. 00678 Int activeZIndex_; 00679 00680 // Somewhat limited-use state, saved here for 'efficiency'. Indicates 00681 // that the last call to conformsToRstrs(), conformsToCS(), or 00682 // conformsToZIndex(), passed the respective compatibility tests. 00683 // (See conformed(), below). Intended to be set only in the methods 00684 // conformsToRstrs(), conformsToCS() and setActiveZIndex_(), respectively. 00685 Bool rstrsConformed_, csConformed_, zIndexConformed_; 00686 00687 // Returns result of last call to conformsTo(WCH&). Methods like showValue() 00688 // which don't have access to the wch can use it instead, but that 00689 // shifts the burden elsewhere of being sure that conformsTo() was called 00690 // for the current WCH. When possible, it is generally better and safer 00691 // to call conformsTo(wch) directly when needed, rather than querying this. 00692 Bool conformed() { 00693 return rstrsConformed_ && csConformed_ && zIndexConformed_; } 00694 00695 // Set (coordinate) state of WCH's WC. Called by WCH::executeSizeControl(). 00696 // (See important notes on interface and implementation of this function 00697 // in the class synopsis above). 00698 virtual Bool sizeControl(WorldCanvasHolder& wcHolder, 00699 AttributeBuffer& holderBuf) = 0; 00700 00701 // Retrieve position, motion, refresh and display event handler lists. 00702 // <group> 00703 virtual const List<WCPositionEH*> *positionEventHandlerList() 00704 { return &itsPositionEHList; } 00705 virtual const List<WCMotionEH*> *motionEventHandlerList() 00706 { return &itsMotionEHList; } 00707 virtual const List<WCRefreshEH*> *refreshEventHandlerList() 00708 { return &itsRefreshEHList; } 00709 virtual const List<DisplayEH*> *displayEventHandlerList() 00710 { return &itsDisplayEHList; } 00711 // </group> 00712 00713 // Position, motion and refresh event handlers that will generally 00714 // be called by a WorldCanvasHolder. 00715 // <group> 00716 virtual void positionEH(const WCPositionEvent &ev); 00717 virtual void motionEH(const WCMotionEvent &ev); 00718 virtual void refreshEH(const WCRefreshEvent& ev) = 0; 00719 // </group> 00720 00721 // clean up the memory used by this DisplayData 00722 virtual void cleanup() = 0; 00723 00724 // (Required) copy constructor. 00725 DisplayData(const DisplayData &other); 00726 00727 // (Required) copy assignment. 00728 void operator=(const DisplayData &other); 00729 00730 private: 00731 00732 // Colormap for this DisplayData, and its weight. 00733 Colormap *itsColormap; 00734 Float itsColormapWeight; 00735 00736 // A list of WorldCanvasHolders for which this DisplayData works. 00737 // The list is maintained by the DisplayData itself based on the 00738 // notify routines used by the WorldCanvasHolder. This can be used, 00739 // for example, to find which WorldCanvas belongs to which 00740 // WorldCanvasHolder. 00741 List<WorldCanvasHolder*> itsWCHList; 00742 00743 // Lists of position, motion, refresh and display event handlers. 00744 List<WCPositionEH*> itsPositionEHList; 00745 List<WCMotionEH*> itsMotionEHList; 00746 List<WCRefreshEH*> itsRefreshEHList; 00747 List<DisplayEH*> itsDisplayEHList; 00748 00749 // DD 'Absolute Pixel Coordinates', e.g. channel numbers, are internally 00750 // 0-based (begin numbering at 0), but certain external user-interface 00751 // functions (e.g. showPosition(), used for position tracking) have 00752 // produced 1-based output traditionally for the glish-based viewer. 00753 // uiBase_, and related methods uiBase() and setUIBase(), allow newer 00754 // (python/Qt-based) code to cause external ui functions like showValue() 00755 // report 0-based values instead. Unless setUIBase(0) is called, the 00756 // traditional 1-based reporting behavior is retained by default. 00757 00758 Int uiBase_; // (initialized to 1). 00759 }; 00760 00761 00762 } //# NAMESPACE CASA - END 00763 00764 #endif
1.5.1