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