/*
* 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:
*
* rView thumbnail viewer class. Unlike the regular MDD viewers (e.g.
* rviewImage) this is not derived from rviewDisplay because it can
* display any number of MDD objects in contrast to regular viewers
* which manage exactly one object.
*
* COMMENTS:
* None
*/
// 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
#include
#include "wx_pixmap.h"
#include "labelManager.hh"
#ifdef EARLY_TEMPLATE
#define __EXECUTABLE__
#endif
#include "rviewPrefs.hh"
#include "rviewTypes.hh"
#include "rviewUtils.hh"
#include "rviewThumb.hh"
#include "raslib/rmdebug.hh"
#include "rasodmg/ref.hh"
#include "rasodmg/marray.hh"
const int rviewThumb::thumb_width = 450;
const int rviewThumb::thumb_height = 300;
const int rviewThumb::thumb_imgwidth = 100;
const int rviewThumb::thumb_perline = 4;
const int rviewThumb::thumb_space = 32;
const int rviewThumb::thumb_border = 8;
const int rviewThumb::thumb_scrstep = 8;
const int rviewThumb::thumb_pgstep = 8;
const int rviewThumb::thumb_chkwidth = 100;
const int rviewThumb::thumb_chkheight = 30;
const int rviewThumb::thumb_minwidth = 10;
const int rviewThumb::thumb_maxwidth = 2000;
const int rviewThumb::thumb_mincols = 1;
const int rviewThumb::thumb_maxcols = 16;
const int rviewThumb::thumb_cheight = 64;
const int rviewThumb::thumb_twidth = 80;
const int rviewThumb::thumb_theight = 50;
const int rviewThumb::thumb_prjwidth = 60;
/*
* The thumbnail canvas class
*/
thumbCanvas::thumbCanvas(rviewThumb *par, int x, int y, int width, int height) : wxCanvas((wxWindow*)par, x, y, width, height, 0)
{
parent = par;
brush.SetStyle(wxSOLID);
brush.SetColour((char)0xc0, (char)0xc0, (char)0xc0);
SetBackground(&brush);
font = new wxFont(12, wxROMAN, wxNORMAL, wxNORMAL);
}
thumbCanvas::~thumbCanvas(void)
{
SetBackground(NULL);
delete font;
}
void thumbCanvas::OnPaint(void)
{
int thumbs, thumbsperline;
int gridX, gridY;
wxPixmap *thumbnail;
wxUpdateIterator upd(this);
//wxRect rect;
int startx, starty, endx, endy, w, h, posx, posy;
int scrollx, scrolly;
int maxy, runx, runy;
//cout << "thumbCanvas::OnPaint" << endl;
parent->getThumbInfo(thumbs, thumbsperline);
parent->getGridInfo(gridX, gridY);
if ((thumbs <= 0) || (thumbsperline <= 0) || (gridX <= 0) || (gridY <= 0)) return;
GetClientSize(&w, &h);
scrollx = rviewThumb::thumb_scrstep * GetScrollPos(wxHORIZONTAL);
scrolly = rviewThumb::thumb_scrstep * GetScrollPos(wxVERTICAL);
startx = (scrollx / gridX); endx = ((scrollx + w + gridX - 1) / gridX);
starty = (scrolly / gridY); endy = ((scrolly + h + gridY - 1) / gridY);
posx = rviewThumb::thumb_space / 2 + gridX * startx;
posy = rviewThumb::thumb_space / 2 + gridY * starty;
maxy = (thumbs + thumbsperline - 1) / thumbsperline;
if ((startx >= thumbsperline) || (endx < 0)) return;
if ((starty >= maxy) || (endy < 0)) return;
if (startx < 0) startx = 0;
if (endx >= thumbsperline) endx = thumbsperline-1;
if (starty < 0) starty = 0;
if (endy >= maxy) endy = maxy - 1;
BeginDrawing();
SetFont(font);
while (upd)
{
char caption[STRINGSIZE];
runx = posx;
for (w = startx; w <= endx; w++, runx += gridX)
{
runy = posy;
for (h = starty; h <= endy; h++, runy += gridY)
{
if ((thumbnail = parent->getPixmapNumber(h * thumbsperline + w, caption)) != NULL)
{
float tw, th;
/*cout << "Pixmap " << w << ' ' << h << ": " << (void*)thumbnail << ", at " << runx << ' ' << runy
<< ", width " << thumbnail->getWidth() << ", height " << thumbnail->getHeight()
<< ", depth " << thumbnail->getDepth() << ", ddepth " << thumbnail->getModeDepth() << endl;*/
// Pixmaps have the canvas coordinate system, text has the _scrolled_ canvas cosys!
thumbnail->plotPixmap(runx - scrollx, runy - scrolly);
GetTextExtent(caption, &tw, &th);
tw = ((float)(thumbnail->getWidth()) - tw) / 2;
th = thumbnail->getHeight();
DrawText(caption, runx + tw, runy + th);
}
}
}
upd++;
}
SetFont(NULL);
EndDrawing();
}
void thumbCanvas::updateDisplay(void)
{
if (parent->IsShown())
{
int cw, ch;
GetClientSize(&cw, &ch);
SetClippingRegion(0, 0, cw, ch);
OnPaint();
DestroyClippingRegion();
}
}
/*
* The rviewThumb class for displaying thumbnails of images
*/
rviewThumb::rviewThumb(void) : rviewFrame(NULL, "", 0, 0, thumb_width, thumb_height)
{
int x, y, tw, py;
wxMenu *menu;
wxMenu *setup;
wxMenu *submenu;
char buffer[STRINGSIZE];
thumbsperline = 4; if (prefs->thumbCols > 0) thumbsperline = prefs->thumbCols;
projstep = 1; if (prefs->thumbProjstep > 0) projstep = prefs->thumbProjstep;
doValToCspace = (prefs->rgbSpace != 0); doFullRangeCspace = (prefs->rgbSpace == 2);
dimproj = prefs->thumbProjdim;
imgWidth = 100; if (prefs->thumbWidth > 0) imgWidth = prefs->thumbWidth;
if (imgWidth < thumb_minwidth) imgWidth = thumb_minwidth;
if (imgWidth > thumb_maxwidth) imgWidth = thumb_maxwidth;
thumbs = 0; numPixmaps = 0; maxHeight = -1;
listHead = NULL; csmap = NULL; canDoCspace = FALSE;
gridX = 0; gridY = 0;
menu = new wxMenu;
menu->Append(MENU_THUMB_DATA_CLOSE, "");
submenu = new wxMenu;
submenu->Append(MENU_THUMB_CSPACE_ON, "", NULL, TRUE);
submenu->Append(MENU_THUMB_CSPACE_FULL, "", NULL, TRUE);
submenu->Append(MENU_THUMB_CSPACE_EDIT, "");
setup = new wxMenu;
setup->Append(MENU_THUMB_SETUP_CSPACE, "", submenu, NULL);
mbar = new wxMenuBar;
sprintf(buffer, "&%s", lman->lookup("menThumbData"));
mbar->Append(menu, buffer);
sprintf(buffer, "&%s", lman->lookup("menThumbSetup"));
mbar->Append(setup, buffer);
mbar->Check(MENU_THUMB_CSPACE_ON, doValToCspace);
mbar->Check(MENU_THUMB_CSPACE_FULL, doFullRangeCspace);
configureCspace(FALSE);
GetClientSize(&x, &y);
panel = new wxPanel((wxWindow*)this, 0, thumb_border, x, thumb_cheight);
panel->SetLabelPosition(wxVERTICAL);
x -= 2*thumb_border; y -= 2*thumb_border + thumb_cheight;
canvas = new thumbCanvas(this, thumb_border, thumb_border + thumb_cheight, x, y);
tw = (x - 4*thumb_border - 2*thumb_prjwidth) / 3;
py = thumb_border;
projString[0] = '\0';
project = new rviewText(panel);
thumbProj = new rviewText(panel, dimproj);
thumbStep = new rviewText(panel, projstep);
thumbWidth = new rviewText(panel, imgWidth);
thumbCols = new rviewText(panel, thumbsperline);
SetMenuBar(mbar);
label();
frameWidth=-1;
frameHeight=-1;
OnSize(x, y);
OnSize(x, y);
Show(TRUE);
}
rviewThumb::~rviewThumb(void)
{
if (thumbs != 0)
{
int i;
rviewThumbList *tlst = listHead;
for (i=0; inext; delete listHead;
}
}
if (csmap != NULL) delete csmap;
}
void rviewThumb::configureCspace(bool mode)
{
mbar->Enable(MENU_THUMB_SETUP_CSPACE, mode);
mbar->Enable(MENU_THUMB_CSPACE_ON, mode);
mbar->Enable(MENU_THUMB_CSPACE_FULL, mode);
mbar->Enable(MENU_THUMB_CSPACE_EDIT, mode);
}
// Deletes all the pixmaps for one MDD object
void rviewThumb::deletePixmapChain(rviewThumbList *tlst)
{
if (tlst->pixmaps != NULL)
{
rviewThumbPixList *tplst, *tplast;
tplst = tlst->pixmaps;
while (tplst != NULL)
{
//cout << " delete " << (void*)tplst << endl;
tplast = tplst; tplst = tplst->next;
if (tplast->pixmap != NULL) delete tplast->pixmap;
delete tplast;
numPixmaps--;
}
tlst->numPix = 0;
tlst->pixmaps = NULL;
}
}
// Creates a pixmap chain for a given MDD object
int rviewThumb::pixmapsFromMDD(rviewThumbList *tlst)
{
rviewThumbPixList *newPixmap, *lastPixmap;
int i, projval;
bool pixLoop;
//cout << "pixmapsFromMDD" << endl;
// delete old pixmaps
deletePixmapChain(tlst);
lastPixmap = NULL;
if (dimproj >= 0)
{
projval = pt1[dimproj];
}
// Create all thumbnails for this object. This is 1 for 2D objects, any number for 3+D objects
do
{
pixLoop = FALSE;
newPixmap = new rviewThumbPixList;
newPixmap->next = NULL;
newPixmap->dimproj = dimproj; newPixmap->projval = projval;
if (lastPixmap == NULL)
{
tlst->pixmaps = newPixmap;
}
else
{
lastPixmap->next = newPixmap;
}
lastPixmap = newPixmap;
try
{
if ((newPixmap->pixmap = buildThumbnail(tlst->mdd, tlst->baseType, newPixmap->dimproj, newPixmap->projval)) == NULL)
{
cerr << lman->lookup("errorProjThumb") << endl;
return 0;
}
}
catch (r_Error &errObj)
{
cerr << errObj.what() << endl;
return 0;
}
(tlst->numPix)++; numPixmaps++;
i = newPixmap->pixmap->getHeight();
if (i > maxHeight)
{
maxHeight = i;
}
if (dimproj >= 0)
{
projval += projstep;
if (projval <= pt2[dimproj]) pixLoop = TRUE;
}
}
while (pixLoop);
return 1;
}
int rviewThumb::addMDD(r_Ref &newMdd)
{
rviewThumbList *newItem;
int i;
r_Object *mo;
bool oldCstate;
RMDBGONCE(3, RMDebug::module_applications, "rviewThumb", "addMDD(...)");
if ((newItem = new rviewThumbList) == NULL) return 0;
oldCstate = canDoCspace;
// Init object-dependent internal data?
if (projString[0] == '\0')
{
// No ==> init to a decent default:
initForObject(newMdd);
}
mo = (r_Object*)(&(*newMdd));
newItem->mdd = newMdd; newItem->baseType = rviewGetBasetype(mo);
newItem->numPix = 0; newItem->next = NULL; newItem->pixmaps = NULL;
if (pixmapsFromMDD(newItem) == 0)
{
deletePixmapChain(newItem);
delete newItem; return 0;
}
// If it was true before it's true now.
if (oldCstate)
canDoCspace = TRUE;
else
{
// Otherwise try the transition FALSE -> TRUE
if (canDoCspace)
{
// Enabling the parent automatically enables the children too, so reset them...
mbar->Enable(MENU_THUMB_SETUP_CSPACE, TRUE);
mbar->Enable(MENU_THUMB_CSPACE_FULL, doValToCspace);
mbar->Enable(MENU_THUMB_CSPACE_EDIT, doValToCspace);
}
}
if (thumbs == 0)
{
listHead = newItem;
}
else
{
rviewThumbList *tlst = listHead;
for (i=1; inext;
tlst->next = newItem;
}
thumbs++;
updateCanvasSize();
return 1;
}
int rviewThumb::deleteMDD(r_Ref &obsMdd)
{
rviewThumbList *last, *tlst;
int i;
RMDBGONCE(3, RMDebug::module_applications, "rviewThumb", "deleteMDD(...)");
last = NULL; tlst = listHead;
for (i=0; imdd == obsMdd) break;
last = tlst; tlst = tlst->next;
}
if (i < thumbs)
{
deletePixmapChain(tlst);
if (last == NULL)
{
listHead = tlst->next;
}
else
{
last->next = tlst->next;
}
delete tlst;
thumbs--;
// Removing a thumbnail means a new layout and new bounding boxes
maxHeight = 0; tlst = listHead;
for (i=0; ipixmaps;
while (tplst != NULL)
{
ph = tplst->pixmap->getHeight();
if (ph > maxHeight) maxHeight = ph;
tplst = tplst->next;
}
tlst = tlst->next;
}
// Close thumbnail viewer when the last thumbnail has been deleted
if (thumbs <= 0)
{
this->Close(TRUE);
}
else
{
updateCanvasSize();
}
return 1;
}
return 0;
}
void rviewThumb::setLayout(int width, int npl)
{
imgWidth = width; thumbsperline = npl;
updateCanvasSize();
}
void rviewThumb::label(void)
{
SetTitle(lman->lookup("titleThumb"));
mbar->SetLabelTop(0, lman->lookup("menThumbData"));
mbar->SetLabel(MENU_THUMB_DATA_CLOSE, lman->lookup("menThumbDataClose"));
mbar->SetLabelTop(1, lman->lookup("menThumbSetup"));
mbar->SetLabel(MENU_THUMB_SETUP_CSPACE, lman->lookup("menCspaceTitle"));
mbar->SetLabel(MENU_THUMB_CSPACE_ON, lman->lookup("menCspaceOn"));
mbar->SetLabel(MENU_THUMB_CSPACE_FULL, lman->lookup("menCspaceFull"));
mbar->SetLabel(MENU_THUMB_CSPACE_EDIT, lman->lookup("menCspaceEdit"));
project->SetLabel(lman->lookup("textProjString"));
thumbProj->SetLabel(lman->lookup("textThumbProjDim"));
thumbStep->SetLabel(lman->lookup("textThumbProjStep"));
thumbWidth->SetLabel(lman->lookup("textThumbWidth"));
thumbCols->SetLabel(lman->lookup("textThumbColumns"));
}
int rviewThumb::process(wxObject &obj, wxEvent &evt)
{
int type = evt.GetEventType();
if (type == wxEVENT_TYPE_TEXT_ENTER_COMMAND)
{
char buffer[STRINGSIZE];
int newVal;
if (&obj == (wxObject*)thumbWidth)
{
newVal = atoi(thumbWidth->GetValue());
if ((newVal < thumb_minwidth) || (newVal > thumb_maxwidth))
{
sprintf(buffer, "%d", imgWidth);
thumbWidth->SetValue(buffer);
}
else
{
newThumbWidth(newVal);
}
return 1;
}
if (&obj == (wxObject*)thumbCols)
{
newVal = atoi(thumbCols->GetValue());
if ((newVal < thumb_mincols) || (newVal > thumb_maxcols))
{
sprintf(buffer, "%d", thumbsperline);
thumbCols->SetValue(buffer);
}
else
{
thumbsperline = newVal;
updateCanvasSize();
}
return 1;
}
if (&obj == (wxObject*)project)
{
if (thumbs > 0)
{
unsigned int oldProj;
int oldFrom, oldTo;
oldProj = dimproj;
if (dimproj >= 0)
{
oldFrom = pt1[dimproj]; oldTo = pt2[dimproj];
}
strcpy(projString, project->GetValue());
if (parseProjection(listHead->mdd) != 0)
{
bool fromScratch = TRUE;
// Determine whether we have to rebuild everything from scratch or not
if ((int)oldProj == dimproj)
{
if (dimproj >= 0)
{
if ((pt1[dimproj] == oldFrom) && (pt2[dimproj] == oldTo)) fromScratch = TRUE;
}
}
rebuildThumbnails(fromScratch);
}
}
return 1;
}
if (&obj == (wxObject*)thumbStep)
{
int oldStep = projstep;
projstep = atoi(thumbStep->GetValue());
if (projstep <= 0)
{
projstep = 1;
thumbProj->SetValue("1");
}
if ((dimMDD > 2) && (oldStep != projstep)) rebuildThumbnails(TRUE);
return 1;
}
if (&obj == (wxObject*)thumbProj)
{
if ((thumbs > 0) && (dimMDD > 2))
{
if (parseProjection(listHead->mdd) != 0)
{
rebuildThumbnails(TRUE);
}
}
return 1;
}
}
return 0;
}
const char *rviewThumb::getFrameName(void) const
{
return "rviewThumb";
}
rviewFrameType rviewThumb::getFrameType(void) const
{
return rviewFrameTypeThumb;
}
void rviewThumb::OnSize(int w, int h)
{
int x, y, tw, py, px;
GetClientSize(&x, &y);
if((x < thumb_width) || (y < thumb_height))
{
frameWidth = x;
frameHeight = y;
SetClientSize(thumb_width, thumb_height);
return;
}
panel->SetSize(0, thumb_border, x, thumb_cheight);
x -= 2*thumb_border; y -= 2*thumb_border + thumb_cheight;
canvas->SetSize(thumb_border, thumb_border + thumb_cheight, x, y);
tw = (x - 2*thumb_prjwidth - 2*thumb_twidth - 6*thumb_border);
py = thumb_border;
px = thumb_border;
project->SetSize(px, py, tw , thumb_theight);
px +=thumb_border + tw;
thumbProj->SetSize(px, py, thumb_prjwidth, thumb_theight);
px +=thumb_prjwidth + thumb_border;
thumbStep->SetSize(px, py, thumb_prjwidth, thumb_theight);
px +=thumb_prjwidth + thumb_border;
thumbWidth->SetSize(px, py, thumb_twidth, thumb_theight);
px +=thumb_twidth + thumb_border;
thumbCols->SetSize(px, py, thumb_twidth, thumb_theight);
}
void rviewThumb::OnMenuCommand(int id)
{
switch (id)
{
case MENU_THUMB_DATA_CLOSE:
this->Close(TRUE); break;
case MENU_THUMB_CSPACE_EDIT:
csmap->openEditor(); break;
case MENU_THUMB_CSPACE_ON:
{
rviewThumbList *tlst = listHead;
int i;
// Don't allow switching off cspace mapping if at least one object is float/double.
for (i=0; ibaseType == rbt_float) || (tlst->baseType == rbt_double)) break;
tlst = tlst->next;
}
if (i < thumbs)
{
mbar->Check(MENU_THUMB_CSPACE_ON, TRUE);
}
else
{
doValToCspace = mbar->Checked(MENU_THUMB_CSPACE_ON);
mbar->Enable(MENU_THUMB_CSPACE_FULL, doValToCspace);
mbar->Enable(MENU_THUMB_CSPACE_EDIT, doValToCspace);
rebuildThumbnails(FALSE);
}
}
break;
case MENU_THUMB_CSPACE_FULL:
doFullRangeCspace = mbar->Checked(MENU_THUMB_CSPACE_FULL);
if (csmap != NULL)
{
csmap->processRange((doFullRangeCspace) ? CSPACE_RANGE_FULL : CSPACE_RANGE_ACTUAL);
}
rebuildThumbnails(FALSE);
break;
default: break;
}
}
int rviewThumb::userEvent(const user_event &ue)
{
if (ue.type == usr_mdd_dying)
{
return deleteMDD(*((r_Ref*)(ue.data)));
}
if (ue.type == usr_cspace_changed)
{
if (ue.data == (void*)csmap)
{
rebuildThumbnails(FALSE);
return 1;
}
}
return 0;
}
// Return the pixmap with number no and write a textual description into
// caption which has to be at least STRINGSIZE bytes large.
wxPixmap *rviewThumb::getPixmapNumber(int no, char *caption)
{
rviewThumbList *tlst = listHead;
int major, minor;
wxPixmap *retPix = NULL;
if (no >= numPixmaps) return NULL;
// major = number of MDD object, minor = number of pixmap for this object
major = 0; minor = 0;
while ((tlst != NULL) && (no > 0))
{
minor = 0;
if (no < tlst->numPix)
{
rviewThumbPixList *tplst = tlst->pixmaps;
while ((tplst != NULL) && (no > 0))
{
tplst = tplst->next; minor++; no--;
}
if (tplst == NULL)
{
retPix = NULL;
break;
}
else
{
//cout << "found " << (void*)(tplst->pixmap) << endl;
retPix = tplst->pixmap;
break;
}
}
else
{
no -= tlst->numPix; tlst = tlst->next; major++;
}
}
if ((retPix == NULL) && (tlst != NULL))
{
if ((no == 0) && (tlst->numPix > 0))
{
retPix = tlst->pixmaps->pixmap;
}
}
if (retPix != NULL)
{
sprintf(caption, "MDD %d [%d]", major, minor*projstep);
}
return retPix;
}
void rviewThumb::getThumbInfo(int &num, int &npl)
{
num = numPixmaps; npl = thumbsperline;
}
void rviewThumb::getGridInfo(int &gx, int &gy)
{
gx = gridX; gy = gridY;
}
void rviewThumb::updateCanvasSize(void)
{
int stepx, stepy;
int scrollx, scrolly;
RMDBGONCE(3, RMDebug::module_applications, "rviewThumb", "updateCanvasSize()");
gridX = imgWidth + thumb_space;
gridY = maxHeight + thumb_space;
scrollx = canvas->GetScrollPos(wxHORIZONTAL); scrolly = canvas->GetScrollPos(wxVERTICAL);
stepx = (gridX * thumbsperline + thumb_scrstep - 1) / thumb_scrstep;
if ((numPixmaps == 0) || (thumbsperline == 0))
{
stepy = 1;
canvas->EnableScrolling(TRUE, FALSE);
canvas->SetScrollRange(wxVERTICAL, 0);
}
else
{
stepy = (((numPixmaps + thumbsperline - 1) / thumbsperline) * gridY + thumb_scrstep - 1) / thumb_scrstep;
canvas->EnableScrolling(TRUE, TRUE);
}
canvas->SetScrollbars(thumb_scrstep, thumb_scrstep, stepx, stepy, thumb_pgstep, thumb_pgstep, scrollx, scrolly);
}
// Init internal variables (e.g. projection-related) according to a sample object
void rviewThumb::initForObject(r_Ref &mddObj)
{
char *data;
int i;
r_Minterval interv;
interv = mddObj->spatial_domain();
dimMDD = interv.dimension();
// freeDims is a bitfield specifying which dimensions are free
if (dimMDD <= 2)
{
freeDims = 3;
}
else
{
if ((dimproj == -1) || (dimproj >= dimMDD)) freeDims = 3;
else
{
if (dimproj == 0) freeDims = 6;
else if (dimproj == 1) freeDims = 5;
else freeDims = 3;
}
}
pt1 = r_Point(dimMDD); pt2 = r_Point(dimMDD);
data = projString;
for (i=0; iSetValue(projString);
parseProjection(mddObj);
}
// Parse the projection string and set up all internal variables that depend on it.
int rviewThumb::parseProjection(r_Ref &mddObj)
{
int x, h;
mapIndex = r_Point(dimMDD);
if (rviewParseProjection(mddObj->spatial_domain(), pt1, pt2, projString, &freeDims, &mapIndex) != dimMDD)
{
cerr << lman->lookup("errorProjection") << endl;
rviewErrorbox eb(lman->lookup("errorProjection")); eb.activate();
return 0;
}
dimproj = -1; dim1 = -1; dim2 = -1;
for (x=0; xlookup("errorProjThumb") << endl;
return 0;
}
//cout << "parseProj: dim1 " << dim1 << ", dim2 " << dim2 << ", dimproj " << dimproj << endl;
// are there 3 free dimensions to begin with?
if (dimproj >= 0)
{
// user-specified projection value overrides default (last free one)
h = atoi(thumbProj->GetValue());
// Now swap around the dimensions as required
if (h == dim1)
{
dim1 = dim2; dim2 = dimproj; dimproj = h;
}
else if (h == dim2)
{
dim2 = dimproj; dimproj = h;
}
// otherwise just keep the default dimproj value
}
dim1 = mapIndex[dim1]; dim2 = mapIndex[dim2];
// Also read the other variables that can change the appearance of the thumbnails
h = atoi(thumbWidth->GetValue());
if ((h >= thumb_minwidth) && (h <= thumb_maxwidth))
{
imgWidth = h;
}
h = atoi(thumbStep->GetValue());
if (h > 0)
{
projstep = h;
}
return 1;
}
wxPixmap *rviewThumb::buildThumbnail(r_Ref &mddObj, rviewBaseType baseType, int dimproject, int projval)
{
char *data;
wxPixmap *pixmap;
wxColour palette[2];
int baseSize;
int x;
r_Minterval thisInterv;
int objdim;
int srcWidth;
r_Point ptlow, pthigh;
RMDBGENTER(3, RMDebug::module_applications, "rviewThumb", "buildThumbnail(...)");
//cout << "thumbnail " << dimproject << ", " << projval << endl;
thisInterv = mddObj->spatial_domain();
objdim = thisInterv.dimension();
// Only data with at least 2 dimensions is allowed
if (objdim < 2)
return NULL;
// Check if all the thumbnails have the same number of dimensions
if (dimMDD != objdim)
{
cerr << "Warning: inconsistent number of dimensions in collection!" << endl;
}
// Make sure the points we use are within the spatial domain of this object, in case
// the objects in this collection don't have a uniform spatial domain.
ptlow = r_Point(dimMDD); pthigh = r_Point(dimMDD);
for (x=0; x= thisInterv[x].low()) ptlow[x] = pt1[x]; else ptlow[x] = thisInterv[x].low();
if (pt2[x] <= thisInterv[x].high()) pthigh[x] = pt2[x]; else pthigh[x] = thisInterv[x].high();
}
//cout << "Corners " << pt1 << ", " << pt2 << endl;
//cout << "low " << ptlow << ", high " << pthigh << endl;
baseSize = (int)(mddObj->get_type_length());
if ((baseType == rbt_float) || (baseType == rbt_double))
{
doValToCspace = TRUE;
mbar->Check(MENU_THUMB_CSPACE_ON, TRUE);
configureCspace(TRUE);
}
rviewFlatProjEnv penv;
penv.mddPtr = mddObj.ptr();
penv.pt1 = ptlow; penv.pt2 = pthigh;
penv.dim1 = dim1; penv.dim2 = dim2;
penv.bt = baseType;
penv.doCspace = doValToCspace;
if (dimproject >= 0)
{
penv.pt1[dimproject] = projval; penv.pt2[dimproject] = projval;
}
srcWidth = (int)(pthigh[dim1] - ptlow[dim1] + 1);
//cout << "srcWidth " << srcWidth << endl;
if (srcWidth < 1) srcWidth = 1;
penv.scale = ((double)imgWidth) / srcWidth;
//cout << "dimproject " << dimproject << ", projval " << projval
// << ", scale " << penv.scale << endl;
//cout << "penv " << penv.pt1 << ", " << penv.pt2 << endl;
if (rviewPrepareFlatProjection(penv) != 0) return NULL;
if (rviewImageTypes[baseType] == RVIEW_IMGTYPE_MONO)
{
palette[0] = wxColour(0,0,0); palette[1] = wxColour(255,255,255);
}
// Colourspace mapping possible for this object?
if (rviewCheckInitCspace(baseType, NULL, mddObj) != 0) canDoCspace = TRUE;
if (doValToCspace)
{
penv.cspaceState = rviewCheckInitCspace(baseType, &csmap, mddObj, doFullRangeCspace, NULL, penv.width, &penv.pitch, &penv.depth, &penv.pad);
if (csmap != NULL) mbar->Enable(MENU_THUMB_CSPACE_EDIT, TRUE);
}
else
penv.cspaceState = 0;
penv.csmap = csmap;
/*if (penv.pitch * penv.height >= 16*1024*1024)
return NULL;*/
if ((data = (char*)malloc(penv.pitch * penv.height)) == NULL)
return NULL;
if (rviewPerformFlatProjection(penv, data) != 0)
{
free(data); return NULL;
}
pixmap = new wxPixmap((wxWindow*)canvas, penv.width, penv.height, penv.depth, penv.pad, data, rviewImage::getPixmapFlags(), (rviewImageTypes[baseType] == RVIEW_IMGTYPE_MONO) ? palette : NULL);
RMDBGEXIT(3, RMDebug::module_applications, "rviewThumb", "buildThumbnail(...) Pixmap " << (void*)pixmap );
return pixmap;
}
void rviewThumb::newThumbWidth(int newWidth)
{
if (newWidth == imgWidth) return;
imgWidth = newWidth;
rebuildThumbnails(FALSE);
}
void rviewThumb::rebuildThumbnails(bool fromScratch)
{
int i, j;
rviewThumbList *tlst;
rviewThumbPixList *tplst;
//cout << "rebuildThumbnails " << fromScratch << endl;
tlst = listHead;
if (fromScratch)
{
// Delete all thumbnail pixmaps, including the chain structure
for (i=0; inext)
{
deletePixmapChain(tlst);
}
maxHeight = 0;
for (i=0, tlst=listHead; inext)
{
if (pixmapsFromMDD(tlst) == 0)
{
cerr << lman->lookup("errorProjThumb") << endl;
}
}
}
else
{
// 1) Delete all the thumbnail pixmaps, but leave the chain intact!
for (i=0; inext)
{
tplst = tlst->pixmaps;
while (tplst != NULL)
{
if (tplst->pixmap != NULL) delete tplst->pixmap;
tplst->pixmap = NULL; tplst = tplst->next;
}
}
// 2) Create new ones. Doing this in two passes is better for the memory allocation
for (i=0, tlst=listHead; inext)
{
tplst = tlst->pixmaps;
while (tplst != NULL)
{
if ((tplst->pixmap = buildThumbnail(tlst->mdd, tlst->baseType, tplst->dimproj, tplst->projval)) == NULL)
{
cerr << lman->lookup("errorProjThumb") << endl;
}
tplst = tplst->next;
}
}
}
// Now adapt the maximum height
maxHeight = 0; tlst = listHead;
for (i=0; inext)
{
tplst = tlst->pixmaps;
while (tplst != NULL)
{
if (tplst->pixmap != NULL)
{
j = tplst->pixmap->getHeight();
if (j > maxHeight) maxHeight = j;
}
tplst = tplst->next;
}
}
updateCanvasSize();
}