/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
/
/**
* PURPOSE:
*
* Central definitions of shared objects and constants, global tool functions.
*
* - All menu codes used in the program (MENU_...)
* - Global tool functions for handling collections, base types, projection
* strings, X events, ... . See ``Global functions''.
* - rviewFrame class which must be the base class of all frames used in rView.
* - rviewFrameMgr class for handling all of rView's frames (dispatching events
* etc)
* - rviewMultiline class for displaying several lines of non-editable text.
* - rviewDialog class which is the base class for all rView's dialog windows.
* - rviewErrorbox class, derived from rviewDialog.
* - rviewProgress class, derived from rviewDialog.
* - rviewResults class for displaying database results and dispatching object
* viewers. Relies on code provided by rviewMDD for scaling/resampling/endian
* conversions.
* - rviewAbout class for displaying information about rView itself.
* - rviewStringSet class for displaying a set of strings in a scrollable
* list box.
*
* COMMENTS:
* none
*/
// Was file included via header? Then mask out all non-template code
#if (!defined(EARLY_TEMPLATE) || !defined(__EXECUTABLE__))
// Standard wxWindows preamble.
#ifdef __GNUG__
#pragma implementation
#endif
// changed in wxWindows 2.4.2:
//#include "wx_prec.h"
#include
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include
#endif
// #include "wb_timer.h" -- PB 2006-jan-01
#include
#include
#include
#include
#ifdef EARLY_TEMPLATE
#define __EXECUTABLE__
#endif
#include "raslib/rmdebug.hh"
#include "raslib/primitivetype.hh"
#include "raslib/structuretype.hh"
#include "rviewUtils.hh"
#include "rviewMDD.hh"
#include "rviewPrefs.hh"
#include "rviewColMap.hh"
#include "rviewDModes.hh"
#include "rviewOSection.hh"
#include "rviewTypes.hh"
#include "rviewThumb.hh"
#include "rviewSound.hh"
#include "rviewTypeMan.hh"
#include "labelManager.hh"
#ifdef __VISUALC__
const int rview_window_extra_height = 24;
const int rview_choice_sub_width = 0;
#else
const int rview_window_extra_height = 0;
const int rview_choice_sub_width = 32;
#endif
/*
* Global data
*/
// Base type to string translation tables
#if (MAXIMUM_DIMENSIONS != 4)
#error "Adapt tables for MAXIMUM DIMENSIONS!"
#endif
// String names of base types
char *rviewBaseTypes[] = {
"none",
"Boolean",
"Char",
"Octet",
"Short",
"UShort",
"Long",
"ULong",
"RGBPixel",
"Float",
"Double"
};
// String names of objects of baseType x and dimension y (-> rviewBaseType)
char *rviewTypeNames[][MAXIMUM_DIMENSIONS] = {
{"?", "?", "?", "?"},
{"BoolString", "BoolImage", "BoolCube", "BoolCube4"},
{"GreyString", "GreyImage", "GreyCube", "GreyCube4"},
{"OctetString", "OctetImage", "OctetCube", "OctetCube4"},
{"ShortString", "ShortImage", "ShortCube", "ShortCube4"},
{"UShortString", "UShortImage", "UShortCube", "UShortCube4"},
{"LongString", "LongImage", "LongCube", "LongCube4"},
{"ULongString", "ULongImage", "ULongCube", "ULongCube4"},
{"RGBString", "RGBImage", "RGBCube", "RGBCube4"},
{"FloatString", "FloatImage", "FloatCube", "FloatCube4"},
{"DoubleString", "DoubleImage" "DoubleCube", "DoubleCube4"}
};
// The same for sets
char *rviewSetNames[][MAXIMUM_DIMENSIONS] = {
{"?", "?", "?", "?"},
{"BoolSet1", "BoolSet", "BoolSet3", "BoolSet4"},
{"GreySet1", "GreySet", "GreySet3", "GreySet4"},
{"OctetSet1", "OctetSet", "OctetSet3", "OctetSet4"},
{"ShortSet1", "ShortSet", "ShortSet3", "ShortSet4"},
{"UShortSet1", "UShortSet", "UShortSet3", "UShortSet4"},
{"LongSet1", "LongSet", "LongSet3", "LongSet4"},
{"ULongSet1", "ULongSet", "ULongSet3", "ULongSet4"},
{"RGBSet1", "RGBSet", "RGBSet3", "RGBSet4"},
{"FloatSet1", "FloatSet", "FloatSet3", "FloatSet4"},
{"DoubleSet1", "DoubleSet", "DoubleSet3", "DoubleSet4"}
};
unsigned char lowerCaseTable[256];
// Various support classes
rviewFrameMgr *frameManager = NULL;
labelManager *lman = NULL;
/*
* GLOBAL functions
*/
// Frees all memory allocated by a collection descriptor.
void rviewDeleteCollection(collection_desc *coll)
{
if (coll != NULL)
{
int i;
collection_desc *ptr = coll;
if (coll->collName != NULL) delete [] coll->collName;
if (coll->collType != NULL) delete [] coll->collType;
if (coll->collInfo != NULL) delete [] coll->collInfo;
for (i=0; inumber; i++)
{
if (coll->mddObjs != NULL)
{
if (!coll->mddObjs[i].mdd.is_null())
{
coll->mddObjs[i].mdd.destroy();
}
}
else if (coll->strObjs != NULL)
{
if (coll->strObjs[i] != NULL)
{
delete [] coll->strObjs[i];
}
}
}
if (coll->mddObjs != NULL) delete [] coll->mddObjs;
if (coll->strObjs != NULL) delete [] coll->strObjs;
delete coll;
}
}
/*
* Support function for rviewParseProjection
*/
static const char *rviewParseIndexMapping(const char *s, int idx, int dims, r_Point *mapIndex)
{
const char *b, *d;
r_Range value;
b = s+1;
if (mapIndex == NULL)
{
cerr << "Mode doesn't support reordering of dimensions." << endl;
}
value = (r_Range)strtol(b, (char**)&d, 0);
if (b == d) return NULL;
if ((value < 0) || (value >= (r_Range)dims))
{
cerr << "Bad dimension index " << value << endl;
value = (r_Range)idx;
}
if (mapIndex != NULL) (*mapIndex)[idx] = value;
while ((*d == ' ') || (*d == '\t')) d++;
if (*d == ']') return d+1;
return NULL;
}
/*
* Translate a projection string (now RasDaMan style, i.e. things
* like *:* are also allowed) into two diagonal r_Points. Returns
* number of dimension of projection string for success, 0 for an error.
*/
int rviewParseProjection(const r_Minterval &interv, r_Point &pt1, r_Point &pt2, const char *projString, unsigned int *freeDims, r_Point *mapIndex)
{
int dims, i;
const char *b, *d;
r_Range value;
if (freeDims != NULL) *freeDims = 0;
dims = interv.dimension();
pt1 = r_Point(dims); pt2 = r_Point(dims);
b = projString; i = 0;
while (*b != '\0')
{
while ((*b == ' ') || (*b == '\t')) b++;
if (*b == ',') b++;
while ((*b == ' ') || (*b == '\t')) b++;
if (*b == '\0') break;
if (i >= dims) return 0;
if (*b == '*')
{
pt1[i] = interv[i].low(); pt2[i] = interv[i].high(); b++;
}
else
{
value = (r_Range)strtol(b, (char**)&d, 0);
// no valid number found?
if (b == d) return 0;
b = d;
if ((value < interv[i].low()) || (value > interv[i].high())) return 0;
pt1[i] = value; pt2[i] = value;
}
if (mapIndex != NULL) (*mapIndex)[i] = i;
while ((*b == ' ') || (*b == '\t')) b++;
if (*b == '[') // Explicit index-mapping?
{
if ((b = rviewParseIndexMapping(b, i, dims, mapIndex)) == NULL) return 0;
}
else if (*b == ':') // the upper boundaries follow after a colon.
{
if (freeDims != NULL) *freeDims |= (1< interv[i].high())) return 0;
}
pt2[i] = value;
while ((*b == ' ') || (*b == '\t')) b++;
if (*b == '[')
{
if ((b = rviewParseIndexMapping(b, i, dims, mapIndex)) == NULL) return 0;
}
}
i++;
}
return i;
}
/*
* Determine the base type of an MDD object, returning a simple identifier.
*/
rviewBaseType rviewGetBasetype(r_Object *obj)
{
rviewBaseType baseType;
const r_Type *bt;
baseType = rbt_none;
// New type schema...
bt = obj->get_type_schema();
if (bt->type_id() == r_Type::MARRAYTYPE)
bt = ((r_GMarray*)obj)->get_base_type_schema();
else if (bt->type_id() == r_Type::COLLECTIONTYPE)
bt = ((r_Collection*)obj)->get_element_type_schema();
if (bt != NULL)
{
if (((r_Type*)bt)->isStructType())
{
if (((r_Base_Type*)bt)->size() == 3)
baseType = rbt_rgb;
else
baseType = rbt_none;
}
else
{
r_Primitive_Type *pt = (r_Primitive_Type *)bt;
switch (pt->type_id())
{
case r_Primitive_Type::BOOL: baseType = rbt_bool; break;
case r_Primitive_Type::CHAR: baseType = rbt_char; break;
case r_Primitive_Type::OCTET: baseType = rbt_uchar; break;
case r_Primitive_Type::SHORT: baseType = rbt_short; break;
case r_Primitive_Type::USHORT: baseType = rbt_ushort; break;
case r_Primitive_Type::LONG: baseType = rbt_long; break;
case r_Primitive_Type::ULONG: baseType = rbt_ulong; break;
case r_Primitive_Type::FLOAT: baseType = rbt_float; break;
case r_Primitive_Type::DOUBLE: baseType = rbt_double; break;
default: baseType = rbt_none; break;
}
}
}
else
{
char *name = (char*)(obj->get_type_name());
if (name != NULL)
{
if (strcmp(name, "GreyImage") == 0) baseType = rbt_char;
else if (strcmp(name, "BoolImage") == 0) baseType = rbt_bool;
else if (strcmp(name, "RGBImage") == 0) baseType = rbt_rgb;
}
}
return baseType;
}
/*
* rviewPrintTypedCell() prints the contents of a cell with a given base type into the buffer,
* returning the number of characters written.
*/
// For internal use only
static void printPrimitiveCell(r_Primitive_Type *primType, char **buff, char *data, int numberBase)
{
char *b = *buff;
switch (numberBase)
{
case 8:
switch (primType->type_id())
{
case r_Primitive_Type::BOOL:
b += sprintf(b, "%3o", *((r_Boolean*)data)); break;
case r_Primitive_Type::CHAR:
b += sprintf(b, "%3o", *((r_Char*)data)); break;
case r_Primitive_Type::OCTET:
b += sprintf(b, "%3o", *((r_Octet*)data)); break;
case r_Primitive_Type::SHORT:
b += sprintf(b, "%6o", *((r_Short*)data)); break;
case r_Primitive_Type::USHORT:
b += sprintf(b, "%6o", *((r_UShort*)data)); break;
case r_Primitive_Type::LONG:
b += sprintf(b, "%11lo", *((r_Long*)data)); break;
case r_Primitive_Type::ULONG:
b += sprintf(b, "%11lo", *((r_ULong*)data)); break;
case r_Primitive_Type::FLOAT:
b += sprintf(b, "%011o", *((r_Long*)data)); break;
case r_Primitive_Type::DOUBLE:
b += sprintf(b, "%011o:%011o", ((r_Long*)data)[0], ((r_Long*)data)[1]); break;
default:
break;
}
break;
case 16:
switch (primType->type_id())
{
case r_Primitive_Type::BOOL:
b += sprintf(b, "%02x", *((r_Boolean*)data)); break;
case r_Primitive_Type::CHAR:
b += sprintf(b, "%02x", *((r_Char*)data)); break;
case r_Primitive_Type::OCTET:
b += sprintf(b, "%02x", *((r_Octet*)data)); break;
case r_Primitive_Type::SHORT:
b += sprintf(b, "%04x", *((r_Short*)data)); break;
case r_Primitive_Type::USHORT:
b += sprintf(b, "%04x", *((r_UShort*)data)); break;
case r_Primitive_Type::LONG:
b += sprintf(b, "%08x", *((r_Long*)data)); break;
case r_Primitive_Type::ULONG:
b += sprintf(b, "%08x", *((r_ULong*)data)); break;
case r_Primitive_Type::FLOAT:
b += sprintf(b, "%08x", *((r_Long*)data)); break;
case r_Primitive_Type::DOUBLE:
b += sprintf(b, "%08x:%08x", ((r_Long*)data)[0], ((r_Long*)data)[1]); break;
default:
break;
}
break;
default:
switch (primType->type_id())
{
case r_Primitive_Type::BOOL:
b += sprintf(b, "%3d", *((r_Boolean*)data)); break;
case r_Primitive_Type::CHAR:
b += sprintf(b, "%3d", *((r_Char*)data)); break;
case r_Primitive_Type::OCTET:
b += sprintf(b, "%3d", *((r_Octet*)data)); break;
case r_Primitive_Type::SHORT:
b += sprintf(b, "%5d", *((r_Short*)data)); break;
case r_Primitive_Type::USHORT:
b += sprintf(b, "%5d", *((r_UShort*)data)); break;
case r_Primitive_Type::LONG:
b += sprintf(b, "%10ld", *((r_Long*)data)); break;
case r_Primitive_Type::ULONG:
b += sprintf(b, "%10ld", *((r_ULong*)data)); break;
case r_Primitive_Type::FLOAT:
b += sprintf(b, "%g", *((r_Float*)data)); break;
case r_Primitive_Type::DOUBLE:
b += sprintf(b, "%g", *((r_Double*)data)); break;
default:
break;
}
break;
}
*buff = b;
}
// For internal use only
void printStructuredCell(r_Structure_Type *structType, char **buff, char *data, int numberBase)
{
r_Type *newType;
unsigned long off;
char *b;
b = *buff;
*b++ = '{';
r_Structure_Type::attribute_iterator iter(structType->defines_attribute_begin());
while (iter != structType->defines_attribute_end())
{
newType = (*iter).type_of().clone();
off = (*iter).offset();
if (newType->isStructType())
{
r_Structure_Type *newStructType = (r_Structure_Type*)newType;
printStructuredCell(newStructType, &b, data + off, numberBase);
}
else
{
r_Primitive_Type *newPrimType = (r_Primitive_Type*)newType;
printPrimitiveCell(newPrimType, &b, data + off, numberBase);
}
delete newType;
*b++ = ',';
iter++;
}
b[-1] = '}'; *b = '\0';
*buff = b;
}
int rviewPrintTypedCell(const r_Type *baseType, char *buffer, char *data, int numberBase)
{
char *b = buffer;
if (((r_Type*)baseType)->isStructType())
{
r_Structure_Type *structType = (r_Structure_Type*)baseType;
printStructuredCell(structType, &b, data, numberBase);
}
else
{
r_Primitive_Type *primType = (r_Primitive_Type*)baseType;
printPrimitiveCell(primType, &b, data, numberBase);
}
return (int)(b - buffer);
}
/*
* Quicksort a char *[]
*/
#define QUICKSORT_STRING_SWAP(x,y) h=array[x]; array[x]=array[y]; array[y]=h;
void rviewQuicksortStrings(char *array[], int from, int to)
{
while (from < to)
{
int i, j;
char *h;
j = (from+to)/2;
QUICKSORT_STRING_SWAP(from, j); j=from;
for (i=from+1; i<=to; i++)
{
if (strcmp(array[i], array[from]) < 0)
{
j++;
QUICKSORT_STRING_SWAP(i, j);
}
}
QUICKSORT_STRING_SWAP(from, j);
if ((j-from) < (to-j))
{
rviewQuicksortStrings(array, from, j-1);
from = j+1;
}
else
{
rviewQuicksortStrings(array, j+1, to);
to = j-1;
}
}
}
/*
* Init character lookup tables (e.g. lower case table)
*/
void rviewInitCharacterTables(void)
{
int i;
for (i=0; i<256; i++) lowerCaseTable[i] = tolower(i);
}
#define LOOKUP_KEYWORD_CORE \
while (count != 0) \
{ \
b = (const unsigned char*)(kti[pos].keyword); \
d = (const unsigned char*)key; \
while (TRANSLATE_CHARACTER(b) == TRANSLATE_CHARACTER(d)) \
{ \
if (*b == 0) break; b++; d++; \
} \
if ((*b == 0) && (*d == 0)) return kti[pos].ident; \
if (TRANSLATE_CHARACTER(b) >= TRANSLATE_CHARACTER(d)) \
{ \
pos -= step; if (pos < 0) pos = 0; \
} \
else \
{ \
pos += step; if (pos >= tabsize) pos = tabsize - 1; \
} \
step = (step+1) >> 1; count >>= 1; \
}
/*
* Lookup a keyword in a SORTED keyword_to_ident table. Case sensitivity
* is optional but has to match the sorting order of the table, of course.
*/
int rviewLookupKeyword(const char *key, const keyword_to_ident_c *kti, int tabsize, bool caseSensitive)
{
int pos, step, count;
const unsigned char *b, *d;
count = tabsize;
pos = (tabsize + 1) >> 1; if (pos >= tabsize) pos = tabsize - 1;
step = (pos + 1) >> 1;
if (caseSensitive)
{
#define TRANSLATE_CHARACTER(x) (*x)
LOOKUP_KEYWORD_CORE;
#undef TRANSLATE_CHARACTER
}
else
{
#define TRANSLATE_CHARACTER(x) lowerCaseTable[(*x)]
LOOKUP_KEYWORD_CORE;
#undef TRANSLATE_CHARACTER
}
return -1;
}
/* Helper function making sure min/max of the init structure is used by the
colourspace mapper */
static void rviewEnsureCspaceRange(colourspaceMapper *csmap, const colourspace_params *cp)
{
// make sure the min/max values are taken from the init structure as well
if (cp != NULL)
{
// assume it's initialized if either values differs from 0
if ((cp->minVal != 0.0) || (cp->maxVal != 0.0))
{
colourspace_params par;
csmap->getParameters(&par);
par.minVal = cp->minVal;
par.maxVal = cp->maxVal;
// do not do auto-update, otherwise we're stuck in an infinite loop
csmap->colourspaceChanged(&par, FALSE);
//cout << "MIN " << par.minVal << ", MAX " << par.maxVal << endl;
}
}
}
/*
* Check whether colourspace mapping is possible for the given
* base type and return 1 if so. *csmap must be a pointer to the
* colourspaceMapper to use or NULL if there isn't one yet in
* which case a new one will have been created on returning 1.
* If cmap == NULL the function just returns 0 or 1. If the int*
* arguments are not NULL they're set up correctly on exit too.
*/
int rviewCheckInitCspace(rviewBaseType baseType, colourspaceMapper **csmap, r_Ref &mddObj, bool fullRange, r_Minterval *domain, int w, int *newPitch, int *newDepth, int *newPad, int *virtualPitch, const colourspace_params *cp)
{
colourspace_params par;
switch (baseType)
{
case rbt_char:
case rbt_uchar:
case rbt_short:
case rbt_ushort:
if (csmap == NULL) return 1;
if (*csmap == NULL)
{
memcpy(&par, (cp == NULL) ? &(prefs->csp) : cp, sizeof(colourspace_params));
*csmap = new colourspaceMapper(mddObj, baseType, &par, fullRange, domain);
}
else
(*csmap)->bindMapper(mddObj, baseType, fullRange, domain, cp);
rviewEnsureCspaceRange(*csmap, cp);
// always call this and let the mapper sort out whether it has to update
(*csmap)->buildCSTab15();
if (newPitch == NULL) return 1;
if (*newPad < 32) *newPad = 32;
*newDepth = 15;
switch (*newPad)
{
case 32: *newPitch = (w*2 + 3) & ~3; break;
case 64: *newPitch = (w*2 + 7) & ~7; break;
case 128: *newPitch = (w*2 + 15) & ~15; break;
case 256: *newPitch = (w*2 + 31) & ~31; break;
default:
cerr << "Bad pad " << *newPad << endl;
return 0;
}
if (virtualPitch != NULL) *virtualPitch = *newPitch;
return 1;
break;
case rbt_long:
case rbt_ulong: // using 24bpp only makes sense for long
case rbt_float:
case rbt_double: // ... or larger types
{
int baseWidth;
baseWidth = 4*w;
if (csmap == NULL) return 1;
if (*csmap == NULL)
{
memcpy(&par, (cp == NULL) ? &(prefs->csp) : cp, sizeof(colourspace_params));
*csmap = new colourspaceMapper(mddObj, baseType, &par, fullRange, domain);
}
else
(*csmap)->bindMapper(mddObj, baseType, fullRange, domain, cp);
rviewEnsureCspaceRange(*csmap, cp);
(*csmap)->buildCSTab24();
if (newPitch == NULL) return 1;
if (*newPad < 32) *newPad = 32;
*newDepth = 32;
switch (*newPad)
{
case 32: *newPitch = (baseWidth + 3) & ~3; break;
case 64: *newPitch = (baseWidth + 7) & ~7; break;
case 128: *newPitch = (baseWidth + 15) & ~15; break;
case 256: *newPitch = (baseWidth + 31) & ~31; break;
default: cerr << "Bad pad " << *newPad << endl;
return 0;
}
if (virtualPitch != NULL)
*virtualPitch = (baseType == rbt_double) ? 2*(*newPitch) : (*newPitch);
return 1;
}
break;
default: break;
}
return 0;
}
/*
* Smart number conversion functions. They also understand the 0x
* prefix and convert the number correctly.
*/
long asctol(const char *str)
{
return stringtol(str, NULL);
}
int asctoi(const char *str)
{
return (int)stringtol(str, NULL);
}
double asctof(const char *str)
{
return stringtof(str, NULL);
}
long stringtol(const char *str, char **endptr)
{
const char *b = str;
long value;
while (isspace((unsigned int)(*b))) b++;
if ((b[0] == '0') && ((b[1] == 'x') || (b[1] == 'X')))
{
b += 2;
value = strtol(b, endptr, 16);
}
else
{
value = strtol(b, endptr, 10);
}
if ((endptr != NULL) && ((const char*)(*endptr) == b)) *endptr = (char*)str;
return value;
}
double stringtof(const char *str, char **endptr)
{
const char *b = str;
double value;
while (isspace((unsigned int)(*b))) b++;
if ((b[0] == '0') && ((b[1] == 'x') || (b[1] == 'X')))
{
b += 2;
value = (double)strtol(b, endptr, 16);
}
else
{
value = strtod(b, endptr);
}
if ((endptr != NULL) && ((const char*)(*endptr) == b)) *endptr = (char*)str;
return value;
}
/*
* Dynamic string class for easy management of dynamically allocated string storage
*/
const char DynamicString::emptyString[] = "";
DynamicString::DynamicString(void)
{
myString = NULL;
}
DynamicString::DynamicString(const DynamicString &ms)
{
if (ms.myString == NULL)
{
myString = NULL;
}
else
{
myString = new char[strlen(ms.myString) + 1];
strcpy(myString, ms.myString);
}
}
DynamicString::DynamicString(const char *str)
{
if (str == NULL)
{
myString = NULL;
}
else
{
myString = new char[strlen(str) + 1];
strcpy(myString, str);
}
}
DynamicString::~DynamicString(void)
{
if (myString != NULL) delete [] myString;
}
DynamicString &DynamicString::first(const char *str, unsigned int num)
{
if (myString != NULL)
{
delete [] myString; myString = NULL;
}
if (num != 0)
{
unsigned int len = strlen(str);
if (len > num) len = num;
myString = new char[len + 1];
strncpy(myString, str, len);
myString[len] = '\0';
}
return *this;
}
DynamicString &DynamicString::operator=(const DynamicString &ms)
{
if (myString != NULL)
{
delete [] myString; myString = NULL;
}
if (ms.myString != NULL)
{
myString = new char[strlen(ms.myString) + 1];
strcpy(myString, ms.myString);
}
return *this;
}
DynamicString &DynamicString::operator=(const char *str)
{
if (myString != NULL)
{
delete [] myString; myString = NULL;
}
if (str != NULL)
{
myString = new char[strlen(str) + 1];
strcpy(myString, str);
}
return *this;
}
const char *DynamicString::ptr(void) const
{
if (myString == NULL) return emptyString;
return myString;
}
DynamicString::operator const char*(void) const
{
return ptr();
}
bool DynamicString::operator==(const DynamicString &str) const
{
return (strcmp(ptr(), str.ptr()) == 0);
}
bool DynamicString::operator==(const char *str) const
{
return (strcmp(ptr(), str) == 0);
}
/*
* Generic handler function for events like button- and key-presses.
* It passes the event to the frameManager which then broadcasts
* it to all the frames it knows. If a frame recognizes obj as one
* of its children it claims the event, thus aborting the broadcast.
*/
void rviewEventHandler(wxObject &obj, wxEvent &evt)
{
if (frameManager != NULL)
frameManager->broadcastEvent(obj, evt);
//cout << endl;
}
/*
* rviewFrame member functions.
* This is an abstract class that is only used for deriving other
* (window/frame) classes from it.
*/
rviewFrame::rviewFrame(wxFrame *parent, char *title, int x, int y, int w, int h) : wxFrame(parent, title, x, y, w, h)
{
RMDBGONCE( 3, RMDebug::module_applications, "rviewFrame", "rviewFrame( " << this << ", ...)" );
if (frameManager != NULL)
frameManager->registerFrame(this);
parentFrame = NULL;
// Init the size with illegal values to make sure the first OnSize gets through
frameWidth = -1; frameHeight = -1;
// All the frame's children should be destroyed when the frame is destroyed.
frames = new rviewFrameMgr(TRUE);
}
rviewFrame::~rviewFrame(void)
{
RMDBGONCE( 3, RMDebug::module_applications, "rviewFrame", "~rviewFrame() " << this );
delete frames;
if (frameManager != NULL)
frameManager->deregisterFrame(this);
if (parentFrame != NULL)
{
parentFrame->deregisterChild(this);
}
}
const char *rviewFrame::getFrameName(void) const
{
return "rviewFrame";
}
rviewFrameType rviewFrame::getFrameType(void) const
{
return rviewFrameTypeGeneric;
}
void rviewFrame::setParent(rviewFrame *parent)
{
parentFrame = parent;
}
void rviewFrame::registerChild(rviewFrame *child)
{
child->setParent(this);
frames->registerFrame(child);
}
void rviewFrame::deregisterChild(rviewFrame *child)
{
frames->deregisterFrame(child);
child->setParent(NULL);
}
// Called by the global frame manager when the application is about to die.
int rviewFrame::requestQuit(int level)
{
// Default action on a hard quit: die
if (level != 0)
{
// Do not delete the children, that would upset the frame manager's loop.
frames->setDeleteMode(FALSE); setParent(NULL);
//delete this;
Close(TRUE);
}
return 0;
}
// Called on a user event
int rviewFrame::userEvent(const user_event &ue)
{
// Default action: nothing. Overload function in derived class if you're
// interested in user messages.
return 0;
}
// Called by the rviewFrameMgr object to determine which frame receives an event
int rviewFrame::checkobj(wxObject &obj)
{
return checkobj_rec((wxWindow*)this, obj);
}
// Used internally by rviewFrame::checkobj(); don't access directly. Checks
// recursively all the children of a given frame against obj.
int rviewFrame::checkobj_rec(wxWindow *whence, wxObject &obj)
{
if (&obj == (wxObject*)whence) return 1;
else
{
int i, n;
wxList *list;
list = whence->GetChildren();
n = list->Number();
for (i=0; iNth(i)->Data()), obj) != 0) return 1;
}
}
return 0;
}
// Virtual function. If a derived frame class should refuse to die in some
// circumstances, it must overload his function.
bool rviewFrame::OnClose(void)
{
return TRUE;
}
void rviewFrame::childMouseEvent(wxWindow *child, wxMouseEvent &mevt)
{
// by default this is ignored.
}
/*
* rviewFrameMgr member functions
*/
rviewFrameMgr::rviewFrameMgr(void)
{
listLength = 0; deleteChildren = FALSE;
frameList = NULL; tailList = NULL;
}
rviewFrameMgr::rviewFrameMgr(bool delChild)
{
listLength = 0; deleteChildren = delChild;
frameList = NULL; tailList = NULL;
}
rviewFrameMgr::~rviewFrameMgr(void)
{
int i;
frame_list *list, *last;
// Deletes all the frames and their children
// Unlink all frames first! Otherwise there'll be trouble because the Frame Manager
// will loop over the frames and delete them; but if the frames have a valid parent
// they will deregister there which will screw up the Frame Manager's frame list
// _during the loop_ and hence crash.
list = frameList;
for (i=0; inext;
// If it's the global frame manager it shouldn't delete the children, that's
// wxWindows' job. If it's a manager local to a frame it should delete all
// that frame's children, however.
if (deleteChildren)
{
last->frame->setParent(NULL);
//delete last->frame;
last->frame->Close(TRUE);
}
delete last;
}
}
void rviewFrameMgr::registerFrame(rviewFrame *client)
{
frame_list *entry;
//cout << "frameManager::registerFrame(" << (void*)client << ")" << endl;
if ((entry = new frame_list) == NULL)
{
//cerr << "frameManager: Unable to claim memory!\n" << endl;
return;
}
entry->frame = client; entry->next = NULL;
if (frameList == NULL)
{
frameList = entry; tailList = entry;
}
else
{
tailList->next = entry;
tailList = entry;
}
listLength++;
//cout << "Frame manager: Added frame to list. New length = " << listLength << endl;
//cout << "(anchor = " << (void*)frameList << ", tail = " << (void*)tailList << ")" << endl;
}
void rviewFrameMgr::deregisterFrame(rviewFrame *client)
{
int i;
frame_list *list, *last;
//cout << "frameManager::deregisterFrame(" << (void*)client << ")" << endl;
list = frameList; last = NULL;
for (i=0; iframe == client)
{
list = list->next;
if (last == NULL)
{
delete frameList; frameList = list; last = list;
}
else
{
delete last->next; last->next = list;
}
listLength--;
if (last == NULL) tailList = NULL;
else
{
while (last->next != NULL) last = last->next;
tailList = last;
}
//cout << "Frame manager: Removed frame from list. New length = " << listLength << endl;
//cout << "(anchor = " << (void*)frameList << ", tail = " << (void*)tailList << ")" << endl;
return;
}
last = list; list = list->next;
}
}
int rviewFrameMgr::numberOfFrames(void) const
{
return listLength;
}
void rviewFrameMgr::setDeleteMode(bool delChild)
{
deleteChildren = delChild;
}
// Issues re-label requests to all frames.
void rviewFrameMgr::labelAll(void)
{
int i;
frame_list *list;
//cout << "frameManager::labelAll()" << endl;
list = frameList;
for (i=0; iframe->label();
list = list->next;
}
}
/*
* Broadcasts the event to all frames until one claims the event by returning
* a value != 0. Warning: this function has to be re-entrant!
*/
void rviewFrameMgr::broadcastEvent(wxObject &obj, wxEvent &evt)
{
int i;
frame_list *list;
// Note: the broadcast has to go in two steps, first determining which frame
// knows the object, then terminating the loop and calling the object as the
// last action. The reason is that this function is re-entrant and would
// crash badly if the frame list changed during the loop.
//cout << "frameManager::broadcastEvent()" << endl;
list = frameList;
for (i=0; iframe) << endl;
if (list->frame->checkobj(obj) != 0)
{
//cout << "Frame manager: object known by frame " << (void*)list->frame << endl;
break;
}
list = list->next;
}
//cout << "Frame manager: broadcast " << ((list == NULL) ? "failed" : "successful") << endl;
// Now call the frame.
if (list != NULL) {list->frame->process(obj, evt);}
// Uncomment this if there's any doubt it's re-entrant
//cout << "frameManager::broadcastEvent done" << endl;
}
/*
* Broadcast a quit-message to all frames but the first one (the main frame). There
* are currently two levels, 0 means the frames can yet refuse to die by returning a
* value != 0, every other level doesn't give them this option. Returns 0 for failure.
* This must only be called for the _global_ frame manager!
*/
int rviewFrameMgr::broadcastQuit(int level)
{
int i, status;
frame_list *list;
list = frameList->next; status = 1;
for (i=1; i 0) cout << "delete " << (void*)list << endl;
if (list->frame->requestQuit(level) != 0) status = 0;
list = list->next;
}
if (level == 0) return status;
//cout << "Hard quit OK" << endl;
return 1;
}
/*
* Broadcast a user event to all frames.
*/
int rviewFrameMgr::broadcastUserEvent(const user_event &ue)
{
int i, status;
frame_list *list;
list = frameList; status = 0;
for (i=0; iframe) << endl;
status += list->frame->userEvent(ue);
list = list->next;
}
return status; // number of clients that recognised the event.
}
/*
* rviewMultiline member functions
*/
const int rviewMultiline::multiline_ppc10 = 63;
void rviewMultiline::setupVariables(wxPanel *Panel, int X, int Y, int H, int Lines)
{
int i;
parent = Panel; lines = Lines;
if ((msg = new wxMessage *[lines]) == NULL)
{
cerr << "rviewMultiline::setupVariables(): " << lman->lookup("errorMemory") << endl;
return;
}
for (i=0; ilookup("errorMemory") << endl;
return;
}
length = strlen(Message); base = (char*)Message;
for (i=0, pos=y; (length > 0) && (i cpl)
{
b = base + cpl;
while ((*b > 32) && (b > base)) b--;
if (b <= base) b = base + cpl; else b++;
}
else
{
b = base + length;
}
memcpy(buffer, base, (int)(b - base)); buffer[(int)(b - base)] = '\0';
//cout << buffer << endl;
if (msg[i] == NULL)
{
msg[i] = new wxMessage(parent, buffer, x, pos, W, lHeight, 0, "message");
}
else
{
msg[i]->SetSize(x, pos, W, lHeight, 0);
msg[i]->SetLabel(buffer);
}
length -= (int)(b - base); base = b;
}
while (iGetLabelColour())),
bback(background, wxTRANSPARENT),
bfore(foreground, wxSOLID),
bwell(wellground, wxSOLID),
outlinePen(outline, 1, wxSOLID),
labelFont(12, wxROMAN, wxNORMAL, wxNORMAL),
myLabel(label)
{
wxBrush *dcb;
logicalParent = logParent;
border = dflt_border;
barwidth = dflt_barwidth; barheight = dflt_barheight;
value = val;
vmin = min; vmax = max;
if (vmax <= vmin)
vmax = vmin+1;
dcb = ((wxPanel*)GetParent())->GetDC()->GetBackground();
bback = wxBrush(dcb->GetColour(), dcb->GetStyle());
SetBackground(&bback);
SetFont(&labelFont);
GetDC()->GetTextExtent(myLabel.ptr(), &textx, &texty);
}
rviewSpecialSlider::~rviewSpecialSlider(void)
{
}
int rviewSpecialSlider::GetMin(void) const
{
return vmin;
}
int rviewSpecialSlider::GetMax(void) const
{
return vmax;
}
int rviewSpecialSlider::GetValue(void) const
{
return value;
}
void rviewSpecialSlider::SetRange(int min, int max)
{
if (min < max)
{
vmin = min; vmax = max;
if (value < vmin)
value = vmin;
if (value > vmax)
value = vmax;
Refresh(TRUE);
}
}
void rviewSpecialSlider::SetValue(int val)
{
if ((vmin <= val) && (val <= vmax))
{
float barx, bary, bheight, newbx;
getBarParams(barx, bary, bheight);
value = val;
getBarParams(newbx, bary, bheight);
updateWell(barx, newbx, bary, bheight);
}
}
void rviewSpecialSlider::SetLabel(const char *label)
{
myLabel = label;
GetDC()->GetTextExtent(myLabel.ptr(), &textx, &texty);
Refresh(TRUE);
}
bool rviewSpecialSlider::PositionInWell(float posx, float posy)
{
int y0, y1;
GetClientSize(&cwidth, &cheight);
getWellVert(y0, y1);
if (((float)y0 <= posy) && (posy <= (float)y1))
{
if ((posx >= textx + 2*border) && (posx <= (float(cwidth - border))))
return TRUE;
}
return FALSE;
}
void rviewSpecialSlider::getWellVert(int &y0, int &y1)
{
y0 = cheight - 2*border - barheight;
if (y0 < 0)
y0 = 0;
y0 += border;
y1 = cheight - border;
if (y1 < y0)
y1 = y0;
}
void rviewSpecialSlider::getBarParams(float &posx, float &posy, float &height)
{
int y0, y1;
GetClientSize(&cwidth, &cheight);
posx = (float)((cwidth - 3*border - barwidth - textx) * (value-vmin)) / (vmax - vmin);
if (posx < 0)
posx = 0;
/*cout << "cwidth " << cwidth << ", textx " << textx << ", value " << value << ", border " << border
<< ", barwidth " << barwidth << ", vmin " << vmin << ", vmax " << vmax << ", posx " << posx << endl;*/
posx += (float)(2*border + textx);
getWellVert(y0, y1);
posy = (float)y0;
height = (float)(y1 - y0);
}
int rviewSpecialSlider::calcNewValue(float posx, float posy, int &val, bool checky)
{
int y0, y1;
GetClientSize(&cwidth, &cheight);
getWellVert(y0, y1);
if (!checky || ((float)y0 <= posy) && (posy <= (float)y1))
{
float rem = (float)(cwidth - 3*border - barwidth - textx);
if (rem < 1.0)
rem = 1.0;
val = (int)((((posx - 2*border - textx) * (vmax - vmin)) / rem) + 0.5) + vmin;
if (val < vmin)
val = vmin;
if (val > vmax)
val = vmax;
return 0;
}
return -1;
}
void rviewSpecialSlider::getUpdateInterval(float oldx, float newx, float &clipx, float &clipw)
{
if (oldx < newx)
{
clipx = oldx; clipw = newx - oldx + barwidth;
}
else
{
clipx = newx; clipw = oldx - newx + barwidth;
}
}
void rviewSpecialSlider::updateWell(float oldx, float newx, float posy, float bheight)
{
float clipx, clipw;
getUpdateInterval(oldx, newx, clipx, clipw);
//cout << "CLIP " << clipx << ", " << posy << ", " << clipw << ", " << bheight << endl;
// need to enlarge the clipping region somewhat to make sure everything is redrawn
BeginDrawing();
SetClippingRegion(clipx, 0, clipw+2, cheight);
//Clear();
redrawCore(newx, posy, bheight);
DestroyClippingRegion();
EndDrawing();
}
void rviewSpecialSlider::redrawCore(float x, float y, float bheight)
{
float extx, exty, nx, ny;
char number[32];
// first draw the label
SetFont(&labelFont);
SetTextForeground(&labelColour);
DrawText(myLabel.ptr(), 0, y);
SetPen(&outlinePen);
SetBrush(&bwell);
DrawRectangle(textx + border, y-border, (float)cwidth - textx - border, bheight + 2*border);
SetBrush(&bfore);
DrawRectangle(x, y, (float)barwidth, bheight);
// then draw the current value on top
sprintf(number, "%d", value);
GetDC()->GetTextExtent(number, &extx, &exty);
nx = x + (barwidth - extx)/2; ny = y - exty - border;
SetPen(NULL);
// must use a non-transparent brush. Finally found the right one!
SetBrush(((wxPanel*)GetParent())->GetDC()->GetBackground());
DrawRectangle(0, ny, (float)cwidth, exty);
DrawText(number, nx, ny);
}
void rviewSpecialSlider::OnPaint(void)
{
wxRect rect;
float x, y, bheight;
getBarParams(x, y, bheight);
BeginDrawing();
wxUpdateIterator upd(this);
while (upd)
{
upd.GetRect(&rect);
redrawCore(x, y, bheight);
upd++;
}
EndDrawing();
}
void rviewSpecialSlider::OnEvent(wxMouseEvent &mevt)
{
int type = mevt.GetEventType();
float barx, bary, bheight;
float mx, my;
int newVal = value;
getBarParams(barx, bary, bheight);
mevt.Position(&mx, &my);
if ((type == wxEVENT_TYPE_LEFT_DOWN) || (type == wxEVENT_TYPE_RIGHT_DOWN))
{
if (mx < barx)
{
if (calcNewValue(barx - barwidth, my, newVal, TRUE) != 0)
newVal = value;
}
else if (mx > barx + barwidth)
{
if (calcNewValue(barx + barwidth, my, newVal, TRUE) != 0)
newVal = value;
}
}
else if (type == wxEVENT_TYPE_MOTION)
{
if (mevt.LeftIsDown() || mevt.RightIsDown())
{
if (calcNewValue(mx - barwidth/2, my, newVal, FALSE) != 0)
{
newVal = value;
}
}
}
if (newVal != value)
{
float newbx, newby, newbh;
value = newVal;
getBarParams(newbx, newby, newbh);
updateWell(barx, newbx, bary, bheight);
// additionally we build a regular command event
wxCommandEvent cmd(wxEVENT_TYPE_SLIDER_COMMAND);
//OnCommand(*GetParent(), cmd);
logicalParent->process(*this, cmd);
}
// the entire point of this class is to always pass on the actual mouse event to the parent
logicalParent->childMouseEvent(this, mevt);
}
/*
* rviewDialog member functions.
*/
const int rviewDialog::dialog_width = 300;
const int rviewDialog::dialog_height = 170;
const int rviewDialog::dialog_border = 8;
const int rviewDialog::dialog_buttonsx = 80;
const int rviewDialog::dialog_buttonsy = 30;
const int rviewDialog::dialog_bheight = rviewDialog::dialog_buttonsy + 16;
const int rviewDialog::dialog_lines = 8;
const int rviewDialog::dialog_lheight = 20;
// The strings passed to this function may be labels (first char is a backslash)
// or explicit text.
rviewDialog::rviewDialog(const char *title, const char *message, int buttonNo, const char *buttons[]):
rviewFrame(NULL, "", 0, 0, dialog_width, dialog_height)
{
int i, x, y;
char *string;
panel = NULL; buttonNumber = 0; buttonPressed = 0;
buttonText = new char *[buttonNo + 2];
but = new rviewButton *[buttonNo];
if ((buttonText == NULL) || (but == NULL))
{
cerr << "rviewDialog::rviewDialog(): " << lman->lookup("errorMemory") << endl;
if (buttonText != NULL) delete [] buttonText;
if (but != NULL) delete [] but;
return;
}
buttonNumber = buttonNo;
buttonText[0] = (char*)title; buttonText[1] = (char*)message;
for (i=0; i strlen -1 + 1.
if ((string = new char[strlen(buttonText[i]) + ((i==1) ? 1 : 0)]) == NULL)
{
cerr << "rviewDialog::rviewDialog(): " << lman->lookup("errorMemory") << endl;
while (--i >= 0)
{
if (buttonText[i] != NULL) delete [] buttonText[i];
}
delete [] buttonText; buttonText = NULL;
delete [] but; but = NULL;
buttonNumber = 0;
return;
}
strcpy(string, buttonText[i] + ((i==1) ? 0 : 1)); buttonText[i] = string;
//cout << "buttonText[" << i << "] = " << buttonText[i] << endl;
}
else buttonText[i] = NULL;
}
}
GetClientSize(&x, &y);
panel = new wxPanel((wxWindow*)this, 100, 100, 10, 10);
msg = new rviewMultiline(panel, dialog_border, dialog_border, dialog_lheight, dialog_lines);
//cout << x << ", " << y << endl;
// If the strings are not labels then set them now statically, otherwise they will
// be set in the following label() call.
if (title[0] != '\\')
{
SetTitle((char*)title);
}
// Now handle all buttons.
for (i=0; iSetLabel((char*)buttons[i]);
}
else // do this for the button size.
{
but[i]->SetLabel(lman->lookup(buttons[i]+1));
}
}
OnSize(x, y);
label();
Show(TRUE);
}
rviewDialog::~rviewDialog(void)
{
int i;
// Widgets that were created as children of other wx items are deleted by those items.
// They mustn't be destroyed here!
if (msg != NULL) delete msg;
//if (panel != NULL) delete panel;
if (but != NULL)
{
//for (i=0; iSetSize(0, 0, x, y);
if (buttonText[1][0] == '\\')
msg->rebuild(lman->lookup(buttonText[1]+1), x);
else
msg->rebuild(buttonText[1], x);
// Space out the buttons on the available space.
if (buttonNumber == 0) return;
empty = (x - buttonNumber*dialog_buttonsx) / buttonNumber;
if(empty <0 )
empty=0;
pos = empty/2;
for (i=0; iSetSize(pos, y - (dialog_bheight + dialog_buttonsy)/2, dialog_buttonsx, dialog_buttonsy);
pos += empty + dialog_buttonsx;
}
}
void rviewDialog::label(void)
{
int i, x, y;
//cout << "rviewDialog::label()" << endl;
// If the widgets are labels then set their new values.
panel->GetClientSize(&x, &y);
if (buttonText[0] != NULL)
{
SetTitle(lman->lookup(buttonText[0]));
}
// The message is always stored.
if (buttonText[1][0] == '\\')
msg->rebuild(lman->lookup(buttonText[1]+1), x);
else
msg->rebuild(buttonText[1], x);
for (i=0; iSetLabel(lman->lookup(buttonText[2+i]));
}
}
}
/*
* Process events which are broadcast by the frame manager.
*/
int rviewDialog::process(wxObject &obj, wxEvent &evt)
{
int i, type;
//cout << "rviewDialog::process()" << endl;
for (i=0; i= buttonNumber) return 0;
type = evt.GetEventType();
if (type == wxEVENT_TYPE_BUTTON_COMMAND)
{
buttonPressed = i+1;
}
else
{
buttonPressed = 0;
}
//cout << "rviewDialog::process():" << (void*)this << " Button " << buttonPressed << endl;
return buttonPressed;
}
/*
* Polling interface to the dialog box. Returns the number of the button that
* was pressed, starting from 1 (0 means none). On reading the button number
* is reset to 0.
*/
int rviewDialog::GetButton(void)
{
int val = buttonPressed;
buttonPressed = 0;
return val;
}
/*
* Error box
* (an intrinsically modal special case of a dialog box)
*/
char *rviewErrorboxDefaultButton[1] = {"\\textOK"};
rviewErrorbox::rviewErrorbox(const char *message): rviewDialog("\\errorFrom", message, 1, (const char**)rviewErrorboxDefaultButton)
{
//place this in log file
cerr << lman->lookup("errorFrom") << ' ' << message << endl;
}
rviewErrorbox::rviewErrorbox(const char *title, const char *message, int buttonNo, const char *buttons[]): rviewDialog(title, message, buttonNo, buttons)
{
//place this in log file
cerr << lman->lookup("errorFrom") << ' ' << message << endl;
}
rviewErrorbox::~rviewErrorbox(void) {;}
const char *rviewErrorbox::getFrameName(void) const
{
return "rviewErrorbox";
}
rviewFrameType rviewErrorbox::getFrameType(void) const
{
return rviewFrameTypeErrorbox;
}
int rviewErrorbox::activate(void)
{
int pressed;
MakeModal(TRUE);
while ((pressed = GetButton()) == 0) ::wxYield();
MakeModal(FALSE);
return pressed;
}
// static member functions
char *rviewErrorbox::buildErrorMessage(const char *message, const char *classname, const char *funcname)
{
char *buffer, *b;
int bsize = strlen(message) + 1;
if (classname != NULL)
{
bsize += strlen(classname) + 3; // ": "
// funcname is ignored unless class name is given
if (funcname != NULL)
bsize += strlen(funcname) + 3; // "::"
}
buffer = new char[bsize];
b = buffer;
if (classname != NULL)
{
b += sprintf(b, "%s", classname);
if (funcname != NULL)
b += sprintf(b, "::%s", funcname);
b += sprintf(b, ": ");
}
b += sprintf(b, "%s", message);
return buffer;
}
rviewErrorbox *rviewErrorbox::newErrorbox(const char *message, const char *classname, const char *funcname)
{
char *msg;
rviewErrorbox *box;
msg = buildErrorMessage(message, classname, funcname);
box = new rviewErrorbox(msg);
delete [] msg;
return box;
}
rviewErrorbox *rviewErrorbox::newErrorbox(const char *title, const char *message, int buttonNo, const char *buttons[], const char *classname, const char *funcname)
{
char *msg;
rviewErrorbox *box;
msg = buildErrorMessage(message, classname, funcname);
box = new rviewErrorbox(msg);
delete [] msg;
return box;
}
int rviewErrorbox::reportError(const char *message, const char *classname, const char *funcname)
{
rviewErrorbox *box;
int but;
box = newErrorbox(message, classname, funcname);
but = box->activate();
box->Close(TRUE);
return but;
}
int rviewErrorbox::reportError(const char *title, const char *message, int buttonNo, const char *buttons[], const char *classname, const char *funcname)
{
rviewErrorbox *box;
int but;
box = newErrorbox(title, message, buttonNo, buttons, classname, funcname);
but = box->activate();
box->Close(TRUE);
return but;
}
/*
* rviewProgress members
*/
rviewProgress::rviewProgress(const char *message): rviewDialog("\\messageFrom", message, 1, (const char**)rviewErrorboxDefaultButton)
{
int x, y;
RMDBGONCE( 3, RMDebug::module_applications, "rviewProgress", "rviewProgress( " << lman->lookup("messageFrom") << message << " )" );
GetSize(&x, &y);
y = 2*dialog_border + msg->getMessageHeight() + dialog_bheight;
SetSize(-1, -1, x, y);
// Have to do this to make sure you actually see anything in the window
// Crude, but nothing else seems to work...
Refresh(TRUE); ::wxYield();
// Wait 300ms
::wxStartTimer();
while (::wxGetElapsedTime(FALSE) < 300) ::wxYield();
}
rviewProgress::~rviewProgress(void) {;}
int rviewProgress::process(wxObject &obj, wxEvent &evt)
{
if (rviewDialog::process(obj, evt) != 0)
{
this->Close(TRUE);
return 1;
}
return 0;
}
const char *rviewProgress::getFrameName(void) const
{
return "rviewProgress";
}
rviewFrameType rviewProgress::getFrameType(void) const
{
return rviewFrameTypeProgress;
}
/*
* rviewResult members
*/
const int rviewResult::result_x = 0;
const int rviewResult::result_y = 0;
const int rviewResult::result_width = 320;
const int rviewResult::result_height = 296;
const int rviewResult::result_border = 8;
const int rviewResult::result_lheight = 20;
const int rviewResult::result_header = (8 * rviewResult::result_lheight);
const int rviewResult::result_cwidth = 150;
const int rviewResult::result_twidth = 90;
const int rviewResult::result_theight = 30;
const int rviewResult::result_bwidth = 60;
const int rviewResult::result_bheight = 30;
rviewResult::rviewResult(void): rviewFrame(NULL, "", result_x, result_y, result_width, result_height)
{
RMDBGONCE( 3, RMDebug::module_applications, "rviewResult", "rviewResult() " << this);
setupVariables();
configureGrey();
Show(FALSE);
}
rviewResult::rviewResult(collection_desc *collection): rviewFrame(NULL, "", result_x, result_y, result_width, result_height)
{
setupVariables();
setCollection(collection);
}
rviewResult::~rviewResult(void)
{
RMDBGONCE( 3, RMDebug::module_applications, "rviewResult", "rviewResult() " << this );
int i;
collection_desc *ptr = coll;
user_event ue;
// give all viewers a chance to clean up
ue.type = usr_mdd_dying;
for (i=0; inumber; i++)
{
ue.data = (void*)&(coll->mddObjs[i].mdd);
frames->broadcastUserEvent(ue);
}
// All the widgets are deleted automatically.
if (selectedItems != NULL) delete [] selectedItems;
if (typeManager != NULL) {typeManager->unlinkParent(); typeManager->Close(TRUE);}
rviewDeleteCollection(coll);
}
const char *rviewResult::getFrameName(void) const
{
return "rviewResult";
}
rviewFrameType rviewResult::getFrameType(void) const
{
return rviewFrameTypeResult;
}
void rviewResult::setCollection(collection_desc *collection)
{
int x, y, i;
char res_string[STRINGSIZE];
// In case this is called when the frame already displays a result (shouldn't
// normally happen, though)
if (coll != NULL)
{
rviewDeleteCollection(coll);
delete list;
}
coll = collection;
// Init flags
for (i=0; inumber; i++)
{
coll->mddObjs[i].flags = 0;
}
GetClientSize(&x, &y);
list = new wxListBox(panel, (wxFunction)&rviewEventHandler, "", wxMULTIPLE, result_border, result_border + result_header, x, y - result_header, 0, NULL, wxALWAYS_SB | wxLB_MULTIPLE);
ostrstream memstr(res_string, STRINGSIZE);
for (i=0; inumber; i++)
{
list->Append(mddDescriptorString(memstr, i));
}
if (selectedItems != NULL) delete [] selectedItems;
i = (coll->number + 7) >> 3;
if ((selectedItems = new char[i]) == NULL)
{
cerr << "rviewResult::setCollection(): " << lman->lookup("errorMemory") << endl;
this->Close(TRUE);
return;
}
memset(selectedItems, 0, i);
configureGrey();
label();
// Force resize
frameWidth = -1; frameHeight = -1;
OnSize(x, y);
Show(TRUE);
}
char *rviewResult::mddDescriptorString(ostrstream &memstr, int number)
{
r_GMarray *mdd = coll->mddObjs[number].mdd.ptr();
r_Data_Format fmt = mdd->get_current_format();
memstr.width(3);
memstr << number << ": ("; memstr.width(0);
memstr << mdd->get_type_length() << ") "
<< mdd->spatial_domain() << ' '
<< fmt << '\0';
memstr.seekp(0);
return memstr.str();
}
void rviewResult::label(void)
{
char buffer[STRINGSIZE];
//cout << "labelling " << (void*)mBar << endl;
SetTitle(lman->lookup("titleResult"));
if (mBar != NULL)
{
// Configure all the text in the menu bar
mBar->SetLabel(MENU_RSLT_ITEM_OPENALL, lman->lookup("menRsltItemOpAll"));
mBar->SetLabel(MENU_RSLT_ITEM_THUMBALL, lman->lookup("menRsltItemThumbAll"));
mBar->SetLabel(MENU_RSLT_ITEM_CLOSE, lman->lookup("menRsltItemClose"));
mBar->SetHelpString(MENU_RSLT_ITEM_OPENALL, lman->lookup("helpRsltItemOpAll"));
mBar->SetHelpString(MENU_RSLT_ITEM_THUMBALL, lman->lookup("helpRsltItemThumbAll"));
mBar->SetHelpString(MENU_RSLT_ITEM_CLOSE, lman->lookup("helpRsltItemClose"));
mBar->SetLabel(MENU_RSLT_SLCT_SLCTALL, lman->lookup("menRsltSlctSlctAll"));
mBar->SetLabel(MENU_RSLT_SLCT_CLEAR, lman->lookup("menRsltSlctClear"));
mBar->SetLabel(MENU_RSLT_SLCT_OPEN, lman->lookup("menRsltSlctOpen"));
mBar->SetLabel(MENU_RSLT_SLCT_THUMB, lman->lookup("menRsltSlctThumb"));
mBar->SetLabel(MENU_RSLT_SLCT_DELETE, lman->lookup("menRsltSlctDel"));
mBar->SetLabel(MENU_RSLT_SLCT_ENDIAN, lman->lookup("menRsltSlctEndian"));
mBar->SetLabel(MENU_RSLT_SLCT_TYPEMAN, lman->lookup("menRsltSlctTypeMan"));
mBar->SetLabel(MENU_RSLT_SLCT_INFO, lman->lookup("menRsltSlctInfo"));
mBar->SetHelpString(MENU_RSLT_SLCT_SLCTALL, lman->lookup("helpRsltSlctSlctAll"));
mBar->SetHelpString(MENU_RSLT_SLCT_CLEAR, lman->lookup("helpRsltSlctClear"));
mBar->SetHelpString(MENU_RSLT_SLCT_OPEN, lman->lookup("helpRsltSlctOpen"));
mBar->SetHelpString(MENU_RSLT_SLCT_THUMB, lman->lookup("helpRsltSlctThumb"));
mBar->SetHelpString(MENU_RSLT_SLCT_DELETE, lman->lookup("helpRsltSlctDel"));
mBar->SetHelpString(MENU_RSLT_SLCT_ENDIAN, lman->lookup("helpRsltSlctEndian"));
mBar->SetHelpString(MENU_RSLT_SLCT_TYPEMAN, lman->lookup("helpRsltSlctTypeMan"));
mBar->SetHelpString(MENU_RSLT_SLCT_INFO, lman->lookup("helpRsltSlctInfo"));
mBar->SetLabelTop(0, lman->lookup("menRsltItem"));
mBar->SetLabelTop(1, lman->lookup("menRsltSlct"));
}
if (list != NULL)
{
list->SetLabel(lman->lookup("textResult"));
}
if (group != NULL)
{
group->SetLabel(lman->lookup("textCollHeader"));
sprintf(buffer, "%s: %s", lman->lookup("textCollName"), (coll->collName == NULL) ? "" : coll->collName);
collName->SetLabel(buffer);
sprintf(buffer, "%s: %s", lman->lookup("textCollType"), (coll->collType == NULL) ? "?" : coll->collType);
collType->SetLabel(buffer);
sprintf(buffer, (coll->collInfo == NULL) ? "" : coll->collInfo);
collInfo->SetLabel(buffer);
if (choice != NULL)
{
choice->SetLabel(lman->lookup("dispModeLabel"));
}
}
resampBut->SetLabel(lman->lookup("textOK"));
//cout << "labelled OK" << endl;
}
void rviewResult::OnSize(int w, int h)
{
if (panel != NULL)
{
int x, y;
RMDBGONCE( 3, RMDebug::module_applications, "rviewResult", "OnSize( " << w << ", " << h << " )");
GetClientSize(&x, &y);
if ((frameWidth == x) && (frameHeight == y)) return;
frameWidth = x; frameHeight = y;
panel->SetClientSize(x, y);
x -= 2*result_border; y -= 2*result_border;
if (list != NULL)
list->SetSize(result_border,
result_lheight + result_border + result_header,
x,
y - result_header - result_lheight);
if (group != NULL)
{
group->SetSize(result_border,
result_border,
x,
result_header);
//group->GetClientSize(&x, &y);
x -= 2*result_border; y -=2*result_border;
if (collName != NULL)
collName->SetSize(2*result_border,
result_lheight + result_border,
x,
result_lheight);
if (collType != NULL)
collType->SetSize(2*result_border,
2*result_lheight + result_border,
x,
result_lheight);
if (collInfo != NULL)
collInfo->SetSize(2*result_border,
3*result_lheight + result_border,
x,
result_lheight);
if (choice != NULL)
choice->SetSize(2*result_border,
4*result_lheight + result_border,
result_cwidth - cbfactor,
result_lheight);
}
scaleMode->SetSize(3*result_border/2,
6*result_lheight + result_border,
result_cwidth - 2*cbfactor,
result_lheight);
resampText->SetSize(3*result_border/2 + result_cwidth - cbfactor,
6*result_lheight + result_border,
result_twidth,
result_theight);
resampBut->SetSize(3*result_border/2 + result_cwidth - cbfactor/2 + result_twidth,
6*result_lheight + result_border,
result_bwidth,
result_bheight);
}
}
void rviewResult::openViewer(int itemNo)
{
RMDBGONCE( 3, RMDebug::module_applications, "rviewResult", "openViewer( " << itemNo << " )" );
if ((itemNo < 0) || (itemNo >= coll->number)) return;
rviewDisplay *newDisplay=NULL;
switch (prefs->lastDisplay)
{
case 0:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_IMGFLAT) == 0)
{
newDisplay = new rviewFlatImage(coll->mddObjs + itemNo);
}
}
break;
case 1:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_IMGVOLM) == 0)
{
newDisplay = new rviewVolumeImage(coll->mddObjs + itemNo);
}
}
break;
case 2:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_IMGOSECT) == 0)
{
newDisplay = new rviewOSectionFullImage(coll->mddObjs + itemNo);
}
}
break;
case 3:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_IMGHGHT) == 0)
{
newDisplay = new rviewHeightImage(coll->mddObjs + itemNo);
}
}
break;
case 4:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_CHART) == 0)
{
newDisplay = new rviewChart(coll->mddObjs + itemNo);
}
}
break;
case 5:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_TABLE) == 0)
{
newDisplay = new rviewTable(coll->mddObjs + itemNo);
}
}
break;
case 6:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_SOUND) == 0)
{
newDisplay = new rviewSoundPlayer(coll->mddObjs + itemNo);
}
}
break;
case 7:
{
if ((coll->mddObjs[itemNo].flags & RVIEW_RESDISP_STRVIEW) == 0)
{
newDisplay = new rviewStringViewer(coll->mddObjs + itemNo);
}
}
break;
default:
cerr << "Unsupported display mode " << prefs->lastDisplay << endl;
return;
}
if (newDisplay != NULL)
{
if (newDisplay->openViewer() != 0)
newDisplay->Close(TRUE);
else
{
coll->mddObjs[itemNo].flags |= newDisplay->getViewerType();
registerChild(newDisplay);
}
}
}
/*
* This function must be called whenever the selections of the list box
* change (click / double click) or items in the listbox are modified or
* deleted (this seems to be some wxWindows-internal bug that always
* deselects listbox items if an item was changed).
*/
int rviewResult::updateSelection(void)
{
int i, changes, sel=-1;
char val;
if (selectedItems == NULL) return -1;
changes = 0;
for (i=0; inumber; i++)
{
val = selectedItems[i>>3] & (1<<(i&7));
if (list->Selected(i))
{
if (val == 0) {sel=i; changes++;}
selectedItems[i>>3] |= (1<<(i&7));
}
else
{
if (val != 0) {sel=i; changes++;}
selectedItems[i>>3] &= ~(1<<(i&7));
}
}
if (changes > 1)
{
cerr << "Warning: more than one selection changed!" << endl;
}
configureGrey();
return sel;
}
void rviewResult::operationPrologue(void)
{
::wxBeginBusyCursor();
::wxStartTimer();
}
void rviewResult::operationEpilogue(const char *opname)
{
int elapsed = ::wxGetElapsedTime();
::wxEndBusyCursor();
if (opname != NULL)
{
char buffer[STRINGSIZE];
sprintf(buffer, "%s \"%s\": %dms", lman->lookup("textOpTime"), opname, elapsed);
cout << buffer << endl;
SetStatusText(buffer);
}
}
int rviewResult::parseResampleString(const char *resStr, double *values)
{
int i;
const char *b;
b = resStr; i = 0;
while (*b != 0)
{
while ((*b == ' ') || (*b == '\t')) b++;
if (*b == ',') b++;
if (*b != 0)
{
if (values != NULL) values[i] = atof(b);
while ((*b != ' ') && (*b != '\t') && (*b != ',') && (*b != 0)) b++;
i++;
}
}
return i;
}
int rviewResult::resampleSelection(void)
{
int i, j, res;
double *scale;
r_Dimension dim;
r_Minterval oldInterv, useInterv, newInterv;
r_Ref newMdd;
rviewBaseType baseType;
char buffer[STRINGSIZE];
user_event usr;
char *valStr;
int dimString;
int smode;
const char *operation=NULL;
ostrstream memstr(buffer, STRINGSIZE);
valStr = resampText->GetValue();
dimString = parseResampleString(valStr, NULL);
scale = new double[dimString];
parseResampleString(valStr, scale);
for (i=0; iGetSelection();
operationPrologue();
res = 0;
for (i=0; inumber; i++)
{
if (list->Selected(i))
{
double totalScale = 1.0;
baseType = rviewGetBasetype((r_Object*)(&(*(coll->mddObjs[i].mdd))));
oldInterv = (coll->mddObjs[i].mdd)->spatial_domain();
dim = oldInterv.dimension();
newInterv = r_Minterval(dim); useInterv = r_Minterval(dim);
for (j=0; j<(int)dim; j++)
{
double h;
// Use the entire source object for scaling
useInterv << oldInterv[j];
h = (j < dimString) ? scale[j] : scale[dimString-1]; totalScale *= h;
newInterv << r_Sinterval((r_Range)(oldInterv[j].low()), (r_Range)(oldInterv[j].low() + h*(oldInterv[j].high() - oldInterv[j].low() + 1) - 1));
}
if (smode == 0) // resampling mode
{
if (totalScale > 1.0)
{
operation = lman->lookup("operationUpsamp");
j = mdd_objectScaleInter(coll->mddObjs[i].mdd, useInterv, newMdd, newInterv);
}
else
{
operation = lman->lookup("operationDownsamp");
j = mdd_objectScaleAverage(coll->mddObjs[i].mdd, useInterv, newMdd, newInterv);
}
}
else // simple scale mode
{
operation = lman->lookup("operationScale");
j = mdd_objectScaleSimple(coll->mddObjs[i].mdd, useInterv, newMdd, newInterv);
}
if (j != 0)
{
usr.type = usr_mdd_dying; usr.data = (void*)(&((coll->mddObjs[i]).mdd));
frames->broadcastUserEvent(usr);
coll->mddObjs[i].flags = 0;
(coll->mddObjs[i].mdd).destroy();
coll->mddObjs[i].mdd = newMdd;
res++;
list->SetString(i, mddDescriptorString(memstr, i));
selectedItems[i>>3] &= ~(1<<(i&7));
}
}
}
operationEpilogue(operation);
delete [] scale;
lastSelected = updateSelection();
return res;
}
int rviewResult::process(wxObject &obj, wxEvent &evt)
{
int type = evt.GetEventType();
if (&obj == (wxObject*)list)
{
if (type == wxEVENT_TYPE_LISTBOX_COMMAND)
{
//cout << "rviewResult::process Listbox command" << endl;
lastSelected = updateSelection();
return 1;
}
if (type == wxEVENT_TYPE_LISTBOX_DCLICK_COMMAND)
{
if ((lastSelected >= 0) && (lastSelected < coll->number))
{
// This check is necessary
if (!list->Selected(lastSelected))
{
list->SetSelection(lastSelected, TRUE);
if (selectedItems != NULL) selectedItems[lastSelected>>3] |= (1<<(lastSelected&7));
}
openViewer(lastSelected);
}
return 1;
}
}
if (&obj == (wxObject*)choice)
{
if (type == wxEVENT_TYPE_CHOICE_COMMAND)
{
prefs->lastDisplay = choice->GetSelection();
prefs->markModified();
return 1;
}
}
if (&obj == (wxObject*)resampText)
{
if (type == wxEVENT_TYPE_TEXT_ENTER_COMMAND)
{
resampleSelection();
return 1;
}
}
if (&obj == (wxObject*)resampBut)
{
if (type == wxEVENT_TYPE_BUTTON_COMMAND)
{
resampleSelection();
return 1;
}
}
return 0;
}
int rviewResult::userEvent(const user_event &ue)
{
if (ue.type == usr_viewer_closed)
{
mdd_frame *mf = (mdd_frame*)(ue.data);
int i;
//{FILE *fp=fopen("xxx", "a+"); fprintf(fp, "Received viewer closed %p --- %p, %d\n", mf->mdd.ptr(), coll->mddObjs[0].mdd.ptr(), mf->flags); fclose(fp);}
for (i=0; inumber; i++)
{
// must compare pointers, comparing r_Refs has strange effects on Win
if (mf->mdd.ptr() == coll->mddObjs[i].mdd.ptr()) break;
}
if (i < coll->number)
{
coll->mddObjs[i].flags &= ~(mf->flags);
return 1;
}
}
else if (ue.type == usr_child_closed)
{
if (ue.data == (void*)typeManager) typeManager = NULL;
return 1;
}
else if (ue.type == usr_typeman_convert)
{
convertSelectedItems();
typeManager->Close(TRUE); typeManager = NULL;
return 1;
}
else if (ue.type == usr_close_viewers)
{
Close(TRUE);
return 1;
}
return 0;
}
void rviewResult::convertSelectedItems(void)
{
int itemNo;
user_event usr;
char buffer[STRINGSIZE];
ostrstream memstr(buffer, STRINGSIZE);
operationPrologue();
for (itemNo=0; itemNo < coll->number; itemNo++)
{
if ((list->Selected(itemNo)) && (!coll->mddObjs[itemNo].mdd.is_null()))
{
r_Ref newMdd;
if (typeManager->convert(coll->mddObjs[itemNo].mdd, newMdd) == 0)
{
usr.type = usr_mdd_dying; usr.data = (void*)(&((coll->mddObjs[itemNo]).mdd));
frames->broadcastUserEvent(usr);
coll->mddObjs[itemNo].mdd.destroy();
coll->mddObjs[itemNo].mdd = newMdd;
list->SetString(itemNo, mddDescriptorString(memstr, itemNo));
}
else
{
newMdd.destroy();
}
}
}
operationEpilogue(lman->lookup("operationTypeProj"));
lastSelected = updateSelection();
}
// Set up some variables and widgets in the frame.
void rviewResult::setupVariables(void)
{
int x, y;
char *displayModes[RVIEW_RESDISP_NUMBER];
char *scaleModes[2];
wxMenu *mbarMenus[2];
char buffer[STRINGSIZE];
coll = NULL; panel = NULL; list = NULL; collName = NULL; collType = NULL;
group = NULL; mBar = NULL; typeManager = NULL;
lastSelected = -1;
selectedItems = NULL;
CreateStatusLine(1);
mbarMenus[0] = new wxMenu;
mbarMenus[0]->Append(MENU_RSLT_ITEM_OPENALL, "");
mbarMenus[0]->Append(MENU_RSLT_ITEM_THUMBALL, "");
mbarMenus[0]->Append(MENU_RSLT_ITEM_CLOSE, "");
mbarMenus[1] = new wxMenu;
mbarMenus[1]->Append(MENU_RSLT_SLCT_SLCTALL, "");
mbarMenus[1]->Append(MENU_RSLT_SLCT_CLEAR, "");
mbarMenus[1]->Append(MENU_RSLT_SLCT_OPEN, "");
mbarMenus[1]->Append(MENU_RSLT_SLCT_THUMB, "");
mbarMenus[1]->Append(MENU_RSLT_SLCT_DELETE, "");
mbarMenus[1]->Append(MENU_RSLT_SLCT_ENDIAN, "");
mbarMenus[1]->Append(MENU_RSLT_SLCT_TYPEMAN, "");
mbarMenus[1]->Append(MENU_RSLT_SLCT_INFO, "");
mBar = new wxMenuBar;
sprintf(buffer, "&%s", lman->lookup("menRsltItem"));
mBar->Append(mbarMenus[0], buffer);
sprintf(buffer, "&%s", lman->lookup("menRsltSlct"));
mBar->Append(mbarMenus[1], buffer);
GetClientSize(&x, &y);
panel = new wxPanel((wxWindow*)this, 0, 0, x, y);
x -= 2*result_border; y -= 2*result_border;
// Create a group box surrounding the collection-items
group = new wxGroupBox(panel, "", 0, 0, x, result_header, wxBORDER);
x -= 2*result_border; y -= 2*result_border;
// Create the message widget showing the collection name
collName = new wxMessage(panel, "", 2*result_border, result_lheight + 2*result_border, x, result_lheight, 0, "message");
// The same for the collection base type
collType = new wxMessage(panel, "", 2*result_border, 2*result_lheight + 2*result_border, x, result_lheight, 0, "message");
// The info string
collInfo = new wxMessage(panel, "", 2*result_border, 3*result_lheight + 2*result_border, x, result_lheight, 0, "message");
// And the choice item for the display modes.
// In contrast to the menu stuff non-persistent objects are OK here.
displayModes[0] = lman->lookup("dispModeImage");
displayModes[1] = lman->lookup("dispModeVolume");
displayModes[2] = lman->lookup("dispModeOrtho");
displayModes[3] = lman->lookup("dispModeHeight");
displayModes[4] = lman->lookup("dispModeChart");
displayModes[5] = lman->lookup("dispModeTable");
displayModes[6] = lman->lookup("dispModeSound");
displayModes[7] = lman->lookup("dispModeString");
choice = new rviewChoice(panel, RVIEW_RESDISP_NUMBER, displayModes, lman->lookup("dispModeLabel"));
choice->SetSelection(prefs->lastDisplay);
scaleModes[0] = lman->lookup("textResample");
scaleModes[1] = lman->lookup("textScale");
scaleMode = new rviewChoice(panel, 2, scaleModes);
scaleMode->SetSelection(0);
scaleMode->SetLabel("");
sprintf(buffer, "%f", 1.0);
resampText = new rviewText(panel, buffer);
resampBut = new rviewButton(panel, lman->lookup("textOK"));
choice->GetSize(&x, &y);
cbfactor = x - result_cwidth;
SetMenuBar(mBar);
}
void rviewResult::OnMenuCommand(int id)
{
switch (id)
{
case MENU_RSLT_ITEM_OPENALL:
{
for (int i=0; inumber; i++)
{
openViewer(i);
}
}
break;
case MENU_RSLT_ITEM_THUMBALL:
{
int i;
rviewThumb *thumb;
thumb = new rviewThumb;
for (i=0; inumber; i++)
{
thumb->addMDD(coll->mddObjs[i].mdd);
}
registerChild((rviewFrame*)thumb);
}
break;
case MENU_RSLT_ITEM_CLOSE:
{
this->Close(TRUE);
}
break;
case MENU_RSLT_SLCT_SLCTALL:
{
for (int i=0; inumber; i++)
{
if (!list->Selected(i))
{
list->SetSelection(i, TRUE);
}
}
if (selectedItems != NULL) memset(selectedItems, 0xff, (coll->number + 7) >> 3);
configureGrey();
}
break;
case MENU_RSLT_SLCT_CLEAR:
{
for (int i=0; inumber; i++)
{
if (list->Selected(i))
{
list->SetSelection(i, FALSE);
}
}
if (selectedItems != NULL) memset(selectedItems, 0, (coll->number + 7) >> 3);
configureGrey();
}
break;
case MENU_RSLT_SLCT_OPEN:
{
int i;
for (i=0; inumber; i++)
{
if (list->Selected(i))
openViewer(i);
}
}
break;
case MENU_RSLT_SLCT_THUMB:
{
int i;
for (i=0; inumber; i++)
{
if (list->Selected(i)) break;
}
if (i < coll->number)
{
rviewThumb *thumb;
thumb = new rviewThumb;
for (i=0; inumber; i++)
{
if (list->Selected(i))
thumb->addMDD(coll->mddObjs[i].mdd);
}
registerChild((rviewFrame*)thumb);
}
}
break;
case MENU_RSLT_SLCT_DELETE:
{
int itemNo, j;
user_event usr;
do
{
for (itemNo=0; itemNo < coll->number; itemNo++)
if (list->Selected(itemNo)) break;
if (itemNo >= coll->number) break;
list->Delete(itemNo);
// Notify all open display frames that a particular mdd object will die
usr.type = usr_mdd_dying; usr.data = (void*)(&((coll->mddObjs[itemNo]).mdd));
frames->broadcastUserEvent(usr);
if (!coll->mddObjs[itemNo].mdd.is_null())
{
coll->mddObjs[itemNo].mdd.destroy();
}
(coll->number)--;
for (j=itemNo; jnumber; j++)
{
coll->mddObjs[j] = coll->mddObjs[j+1];
// Don't forget to copy the selection too
selectedItems[j>>3] &= ~(1<<(j&7));
if ((selectedItems[(j+1)>>3] & (1<<((j+1)&7))) != 0) selectedItems[j>>3] |= (1<<(j&7));
}
}
while (1);
lastSelected = updateSelection();
configureGrey();
}
break;
case MENU_RSLT_SLCT_ENDIAN:
{
int itemNo;
user_event ue;
operationPrologue();
ue.type = usr_mdd_dying;
for (itemNo = 0; itemNo < coll->number; itemNo++)
{
if ((list->Selected(itemNo)) && (!coll->mddObjs[itemNo].mdd.is_null()))
{
r_Minterval useInterv;
ue.data = (void*)(&((coll->mddObjs[itemNo]).mdd));
frames->broadcastUserEvent(ue); // close all open viewers
useInterv = coll->mddObjs[itemNo].mdd->spatial_domain();
mdd_objectChangeEndianness(coll->mddObjs[itemNo].mdd, useInterv);
}
}
operationEpilogue(lman->lookup("operationEndian"));
}
break;
case MENU_RSLT_SLCT_TYPEMAN:
if (typeManager == NULL)
{
int itemNo;
const r_Type *sampleType = NULL;
for (itemNo = 0; itemNo < coll->number; itemNo++)
{
if ((list->Selected(itemNo)) && (!coll->mddObjs[itemNo].mdd.is_null()))
{
sampleType = coll->mddObjs[itemNo].mdd->get_base_type_schema();
break;
}
}
/*try {
sampleType = r_Type::get_any_type("struct { struct { float u, float v, float w }, float p, float te, float ed, float den, float vis }");
} catch (r_Error &err) {
cerr << err.what() << endl;
}*/
if (sampleType != NULL)
{
if (typeManager == NULL)
typeManager = new rviewTypeMan(this, sampleType);
}
}
break;
case MENU_RSLT_SLCT_INFO: break;
default: break;
}
}
void rviewResult::configureGrey(void)
{
int i;
mBar->Enable(MENU_RSLT_ITEM_OPENALL, (coll->number > 0));
mBar->Enable(MENU_RSLT_ITEM_THUMBALL, (coll->number> 0));
for (i=0; inumber; i++)
{
if (list->Selected(i)) break;
}
bool enable = (i < coll->number);
mBar->Enable(MENU_RSLT_SLCT_CLEAR, enable);
mBar->Enable(MENU_RSLT_SLCT_OPEN, enable);
mBar->Enable(MENU_RSLT_SLCT_THUMB, enable);
mBar->Enable(MENU_RSLT_SLCT_DELETE, enable);
mBar->Enable(MENU_RSLT_SLCT_ENDIAN, enable);
mBar->Enable(MENU_RSLT_SLCT_TYPEMAN, enable);
mBar->Enable(MENU_RSLT_SLCT_INFO, enable);
}
/*
* rView about window
*/
const int rviewAbout::about_width = 300;
const int rviewAbout::about_height = 150;
const int rviewAbout::about_border = 8;
const int rviewAbout::about_pheight = 50;
const int rviewAbout::about_bwidth = 80;
const int rviewAbout::about_bheight = 30;
const int rviewAbout::about_mheight = 16;
rviewAbout::rviewAbout(void) : rviewFrame(NULL, "", -1, -1, about_width, about_height)
{
labels = NULL; numlines = 0;
panel = new wxPanel((wxWindow*)this, 0, 0, about_width, about_height);
okBut = new rviewButton(panel);
label();
OnSize(about_width, about_height);
}
rviewAbout::~rviewAbout(void)
{
// the messages themselves will be sorted out by the panel destructor.
if (labels != NULL) delete [] labels;
}
const char *rviewAbout::getFrameName(void) const
{
return "rviewAbout";
}
rviewFrameType rviewAbout::getFrameType(void) const
{
return rviewFrameTypeAbout;
}
void rviewAbout::deleteLabels(void)
{
if (labels != NULL)
{
int i;
for (i=0; ilookup("titleAbout"));
okBut->SetLabel(lman->lookup("textOK"));
deleteLabels();
GetClientSize(&x, &y);
y = about_border;
number = atoi(lman->lookup("rviewAboutLineNum"));
if (number >= 1)
{
char lineName[64];
numlines = number;
labels = new wxMessage *[numlines]; x -= 2*about_border;
for (i=0; ilookup(lineName), about_border, y, x, about_mheight, 0, "message");
y += about_mheight;
}
}
SetSize(-1, -1, x, y + about_pheight + rview_window_extra_height);
}
int rviewAbout::process(wxObject &obj, wxEvent &evt)
{
if ((&obj == (wxObject*)okBut) && (evt.GetEventType() == wxEVENT_TYPE_BUTTON_COMMAND))
{
Show(FALSE); return 1;
}
return 0;
}
void rviewAbout::OnSize(int w, int h)
{
int x, y;
GetClientSize(&x, &y);
panel->SetSize(0, 0, x, y);
x -= 2*about_border; y = about_border;
if (panel != NULL)
{
for (int i=0; iSetSize(about_border, y, x, about_mheight);
y += about_mheight;
}
}
x -= about_bwidth; y += (about_pheight - about_bheight)/2;
okBut->SetSize(x/2, y, about_bwidth, about_bheight);
}
/*
* rviewStringSet window
*/
const int rviewStringSet::strset_width = 300;
const int rviewStringSet::strset_height = 250;
const int rviewStringSet::strset_border = 8;
const int rviewStringSet::strset_reserve = 50;
const int rviewStringSet::strset_bwidth = 70;
const int rviewStringSet::strset_bheight = 40;
const int rviewStringSet::strset_mheight = 20;
rviewStringSet::rviewStringSet(collection_desc *desc) : rviewFrame(NULL, "", -1, -1, strset_width, strset_height)
{
int w, h;
char buffer[STRINGSIZE];
panel = new wxPanel((wxWindow*)this, 0, 0, strset_width, strset_height);
list = new wxListBox(panel, (wxFunction)rviewEventHandler, "", wxSINGLE, 0, 0, strset_width, strset_height, desc->number, desc->strObjs, wxALWAYS_SB);
dismiss = new rviewButton(panel);
sprintf(buffer, "%s: %s", lman->lookup("textCollName"), (desc->collName == NULL) ? "" : desc->collName);
collName = new wxMessage(panel, buffer, 0, 0, 10, 10, 0, "message");
sprintf(buffer, "%s: %s", lman->lookup("textCollType"), (desc->collType == NULL) ? "" : desc->collType);
collType = new wxMessage(panel, buffer, 0, 0, 10, 10, 0, "message");
char* tmpChar1 = "message";
char* tmpChar2 = "";
collInfo = new wxMessage(panel, (desc->collInfo == NULL) ? tmpChar2 : desc->collInfo, 0, 0, 10, 10, 0, tmpChar1);
GetClientSize(&w, &h);
label();
OnSize(w, h);
Show(TRUE);
}
rviewStringSet::~rviewStringSet(void)
{
}
const char *rviewStringSet::getFrameName(void) const
{
return "rviewStringSet";
}
rviewFrameType rviewStringSet::getFrameType(void) const
{
return rviewFrameTypeStrSet;
}
void rviewStringSet::label(void)
{
SetTitle(lman->lookup("titleStringSet"));
list->SetLabel(lman->lookup("strSetList"));
dismiss->SetLabel(lman->lookup("textClose"));
}
void rviewStringSet::OnSize(int w, int h)
{
int x, y;
int head;
GetClientSize(&x, &y);
panel->SetSize(0, 0, x, y);
head = 3*(strset_mheight + strset_border);
x -= 2*strset_border; y -= 2*strset_border;
collName->SetSize(strset_border, strset_border, x, strset_mheight);
collType->SetSize(strset_border, strset_mheight + 2*strset_border, x, strset_mheight);
collInfo->SetSize(strset_border, 2*strset_mheight + 3*strset_border, x, strset_mheight);
list->SetSize(strset_border, strset_border + head, x, y - head - strset_reserve);
dismiss->SetSize((x - strset_bwidth) / 2, y + 2*strset_border - (strset_reserve + strset_bheight) / 2, strset_bwidth, strset_bheight);
}
int rviewStringSet::process(wxObject &obj, wxEvent &evt)
{
if (&obj == (wxObject*)dismiss)
{
this->Close(TRUE);
return 1;
}
return 0;
}
int rviewStringSet::getNumItems(void)
{
return list->Number();
}
void rviewStringSet::addItem(const char *string)
{
list->Append((char*)string);
}
char *rviewStringSet::getItem(int number)
{
return list->GetString(number);
}
#ifdef EARLY_TEMPLATE
#undef __EXECUTABLE__
#endif
#endif // !defined(EARLY_TEMPLATE) || !defined(__EXECUTABLE__)
#if (!defined(EARLY_TEMPLATE) || defined(__EXECUTABLE__))
/*
* Templates
*/
// For placement new (DynamicStack template)
#include
/*
* Use malloc/free, placement new and explicit calls to destructors.
* Use placement new when initializing on the stack because that's
* raw memory, use assignment when initializing parameters
*/
template
DynamicStack::DynamicStack(unsigned int gran)
{
number = 0; max = 0;
if ((stack = (T*)malloc(gran * sizeof(T))) != NULL)
{
granularity = gran;
max = granularity;
memset(stack, 0, max * sizeof(T));
}
}
template
DynamicStack::DynamicStack(const DynamicStack &src)
{
number = 0; max = 0;
if ((stack = (T*)malloc(src.max * sizeof(T))) != NULL)
{
granularity = src.granularity;
max = src.max;
memset(stack, 0, max*sizeof(T));
number = src.number;
unsigned int i;
// use loop for class safety
for (i=0; i
DynamicStack::~DynamicStack(void)
{
unsigned int i;
for (i=0; i
int DynamicStack::push(const T &item)
{
if (ensureFree() != 0) return -1;
new(stack + number++) T(item); // placement new
return 0;
}
template
int DynamicStack::pop(T &item)
{
if (number == 0) return -1;
item = stack[--number]; // assignment
stack[number].~T(); // direct destructor call
return 0;
}
template
int DynamicStack::peek(T &item) const
{
if (number == 0) return -1;
item = stack[number-1]; // assignment
return 0;
}
template
unsigned int DynamicStack::getNumber(void) const
{
return number;
}
template
int DynamicStack::ensureFree(void)
{
if (number >= max)
{
if ((stack = (T*)realloc(stack, (max + granularity) * sizeof(T))) == NULL)
{
max = 0; number = 0; return -1;
}
memset(stack + max, 0, granularity * sizeof(T));
max += granularity;
}
return 0;
}
#endif