/*
* 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 table viewer. Can display MDD objects of any dimension and base type (!)
* as tables. Optional modes are decimal, octal and hex number bases.
*
* 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
#ifdef EARLY_TEMPLATE
#define __EXECUTABLE__
#endif
#include "raslib/rmdebug.hh"
#include "raslib/primitivetype.hh"
#include "raslib/structuretype.hh"
#include "rviewTypes.hh"
#include "labelManager.hh"
#include "rviewUtils.hh"
#include "rviewDModes.hh"
#include "rviewPrefs.hh"
const int textCanvas::txcanv_cospace = 8;
const int textCanvas::txcanv_colspace = 16;
const int textCanvas::txcanv_border = rviewDisplay::display_border;
const int rviewTable::table_twidth = 64;
const int rviewTable::table_theight = 50;
const int rviewTable::table_cwidth = 100;
const int rviewTable::table_cheight = 50;
const int rviewTable::table_minwidth = 100;
const int rviewTable::table_minheight = 100;
const int rviewTable::table_ctrly = 64;
const int rviewTable::table_totaly = rviewDisplay::display_cheight + rviewTable::table_ctrly;
textCanvas::textCanvas(wxWindow *parent, int x, int y, int w, int h, long style) : wxCanvas(parent, x, y, w, h, style)
{
wxColour fc(0x10, 0x10, 0x10);
wxColour bc(0xf0, 0xf0, 0xf0);
fore.SetStyle(wxSOLID);
fore.SetColour(fc);
back.SetStyle(wxSOLID);
back.SetColour(bc);
// Don't use wxDEFAULT! Doesn't work on Sun! */
font = new wxFont(12, wxROMAN, wxNORMAL, wxNORMAL);
SetBackground(&back);
SetTextBackground(&bc);
SetTextForeground(&fc);
pen.SetStyle(wxSOLID);
pen.SetColour(fc);
scrollX = 0; scrollY = 0;
}
textCanvas::~textCanvas(void)
{
SetBackground(NULL); SetTextBackground(NULL); SetTextForeground(NULL); pen.SetColour(0, 0, 0);
delete font;
}
void textCanvas::setData(mdd_frame *mf, rviewBaseType bt, unsigned int bs)
{
mddObj = mf->mdd;
dimMDD = (int)(mddObj->spatial_domain().dimension());
baseType = bt;
baseSize = bs;
}
void textCanvas::setStep(int sx, int sy)
{
stepx = sx; stepy = sy;
}
void textCanvas::setProjection(r_Point &p1, r_Point &p2, unsigned int fd, r_Point *mapIndex)
{
pt1 = p1; pt2 = p2; freeDims = fd;
for (dim1=0; dim1= dimMDD)
dim1 = -1;
else if (mapIndex != NULL)
dim1 = (*mapIndex)[dim1];
if (dim2 >= dimMDD)
dim2 = -1;
else if (mapIndex != NULL)
dim2 = (*mapIndex)[dim2];
}
void textCanvas::setCoSys(bool cs, int &cl, int &ct)
{
cosys = cs;
if (cosys)
{
char buffer[STRINGSIZE];
float twidth, theight;
SetFont(font);
if (dim2 < 0)
{
coleft = txcanv_cospace;
sprintf(buffer, "%ld", pt1[dim1]);
GetTextExtent(buffer, &twidth, &theight);
}
else
{
sprintf(buffer, "%ld", (abs(pt1[dim2]) > abs(pt2[dim2])) ? pt1[dim2] :pt2[dim2]);
GetTextExtent(buffer, &twidth, &theight);
coleft = (int)twidth + txcanv_cospace;
}
cotop = (int)theight + txcanv_cospace;
SetFont(NULL);
}
else
{
coleft = 0; cotop = 0;
}
cl = coleft; ct = cotop;
}
void textCanvas::OnPaint(void)
{
wxUpdateIterator upd(this);
wxRect rect;
int w, h, x, y;
r_Point prun = pt1;
wxCanvasDC *cdc;
r_Range startOffX, endOffX, startOffY, endOffY;
float posx, posy;
char textbuff[STRINGSIZE];
bool redrawAll = FALSE;
//cout << "textCanvas::OnPaint()" << endl;
if (dim1 < 0) return;
GetClientSize(&w, &h);
cdc = GetDC();
cdc->BeginDrawing();
cdc->SetMapMode(MM_TEXT);
cdc->SetBrush(&fore);
cdc->SetFont(font);
cdc->SetLogicalFunction(wxCOPY);
w = GetScrollPos(wxHORIZONTAL); h = GetScrollPos(wxVERTICAL);
x = rviewDisplay::display_scrstep * w;
y = rviewDisplay::display_scrstep * h;
// In case of scrolling we have to plot the whole thing. There's a bug in the
// current version of wxWindows that means you don't get any rectangles returned
// that were covered by other windows and are now visible.
if ((w != scrollX) || (h != scrollY))
{
redrawAll = TRUE;
GetClientSize(&rect.width, &rect.height);
rect.x = 0; rect.y = 0;
scrollX = w; scrollY = h;
}
// Use for, not while, because of continue in loop body
for (; upd ; upd++)
{
if (!redrawAll) upd.GetRect(&rect);
// cdc->SetClippingRegion(rect.x, rect.y, rect.width, rect.height);
// Calculate the range to plot.
startOffX = (x + rect.x - txcanv_border - coleft) / stepx;
if (startOffX < 0) startOffX = 0;
if (pt1[dim1] + startOffX > pt2[dim1]) continue;
endOffX = (x + rect.x + rect.width - txcanv_border - coleft + stepx - 1) / stepx;
if (endOffX > pt2[dim1] - pt1[dim1]) endOffX = pt2[dim1] - pt1[dim1];
if (dim2 < 0)
{
startOffY = 0; endOffY = 0;
}
else
{
startOffY = (y + rect.y - txcanv_border - cotop) / stepy;
if (startOffY < 0) startOffY = 0;
if (pt1[dim2] + startOffY > pt2[dim2]) continue;
endOffY = (y + rect.y + rect.height - txcanv_border - cotop + stepy - 1) / stepy;
if (endOffY > pt2[dim2] - pt1[dim2]) endOffY = pt2[dim2] - pt1[dim2];
}
//cout << "table: " << rect.x << ':' << rect.y << ':' << rect.width << ':' << rect.height << " -- " << startOffX << ':' << endOffX << ':' << startOffY << ':' << endOffY << endl;
posy = (float)(startOffY * stepy + txcanv_border + cotop);
r_Ref > mddPtr = (r_Ref >)mddObj;
r_Char *srcBase;
const r_Type *tp;
if ((tp = mddPtr->get_base_type_schema()) == NULL)
{
cerr << "No schema information available" << endl; // FIXME
return;
}
srcBase = (r_Char*)(mddPtr->get_array());
if (dim2 < 0)
{
posx = (float)(startOffX * stepx + txcanv_border + coleft);
for (prun[dim1]=pt1[dim1]+startOffX; prun[dim1]<=pt1[dim1]+endOffX; prun[dim1]++, posx+=stepx)
{
long offset;
offset = ((&((*mddPtr)[prun])) - srcBase) * baseSize;
rviewPrintTypedCell(tp, textbuff, (char*)(srcBase + offset), numberBase);
cdc->DrawText(textbuff, posx, posy);
}
}
else
{
for (prun[dim2]=pt1[dim2]+startOffY; prun[dim2]<=pt1[dim2]+endOffY; prun[dim2]++, posy+=stepy)
{
posx = (float)(startOffX * stepx + txcanv_border + coleft);
for (prun[dim1]=pt1[dim1]+startOffX; prun[dim1]<=pt1[dim1]+endOffX; prun[dim1]++, posx+=stepx)
{
long offset;
offset = ((&((*mddPtr)[prun])) - srcBase) * baseSize;
rviewPrintTypedCell(tp, textbuff, (char*)(srcBase + offset), numberBase);
cdc->DrawText(textbuff, posx, posy);
}
}
}
// Draw coordinate system if necessary
if (cosys)
{
int i;
// Mustn't plot entire lines in one go; the lengths seem to be broken into 16 bit quantities
// internally so you could get overflows. Instead plot just what's visible.
if (startOffX == 0)
{
cdc->DrawLine(txcanv_border, cotop, txcanv_border + coleft, cotop);
}
if (startOffY == 0)
{
cdc->DrawLine(txcanv_border + coleft + startOffX * stepx, cotop, txcanv_border + coleft + (endOffX+1)*stepx, cotop);
}
if (dim2 >= 0)
{
if (startOffX == 0)
{
cdc->DrawLine(coleft, txcanv_border + cotop + startOffY * stepy, coleft, txcanv_border + cotop + (endOffY+1) * stepy);
}
if (startOffY == 0)
{
cdc->DrawLine(coleft, txcanv_border, coleft, txcanv_border + cotop);
}
posx = txcanv_cospace/2;
posy = startOffY * stepy + txcanv_border + cotop;
for (i=startOffY; i<=endOffY; i++, posy+=stepy)
{
sprintf(textbuff, "%ld", pt1[dim2] + i);
cdc->DrawText(textbuff, posx, posy);
}
}
posx = startOffX * stepx + txcanv_border + coleft;
posy = txcanv_cospace/2;
for (i=startOffX; i<=endOffX; i++, posx+=stepx)
{
sprintf(textbuff, "%ld", pt1[dim1] + i);
cdc->DrawText(textbuff, posx, posy);
}
}
}
cdc->SetBrush(NULL);
cdc->SetFont(NULL);
cdc->EndDrawing();
}
void textCanvas::CalcTextExtent(char *b, float &width, float &height)
{
SetFont(font);
GetTextExtent(b, &width, &height);
SetFont(NULL);
}
void textCanvas::EstimateCellSize(int &width, int &height)
{
char buffer[STRINGSIZE];
float twidth, theight;
sprintf(buffer, " ,");
switch (numberBase)
{
case 8: sprintf(buffer+2, "%o", 255); break;
case 16: sprintf(buffer+2, "%x", 255); break;
default: sprintf(buffer+2, "%d", 255); break;
}
CalcTextExtent(buffer, twidth, theight);
width = (int)(baseSize * twidth + txcanv_colspace);
height = (int)(1.5 * theight);
}
void textCanvas::setNumberBase(int newBase)
{
numberBase = newBase;
}
/*
* Class to display tables
*/
const char *rviewTable::view_StepSize = "stepSize";
const char *rviewTable::view_ScrollPos = "scrollPos";
const char *rviewTable::view_CoSys = "coordSys";
const char *rviewTable::view_NumBase = "numberBase";
rviewTable::rviewTable(mdd_frame *mf, unsigned int flags) : rviewDisplay(mf, table_ctrly, flags)
{
int w, h, i;
char *b;
RMDBGONCE(3, RMDebug::module_applications, "rviewTable", "rviewTable()");
// Mode defaults, move to prefs later on
stepx = prefs->tableStepx; stepy = prefs->tableStepy;
cosys = prefs->tableCosys; numberBase = prefs->tableMode;
GetClientSize(&w, &h);
w -= 2*display_cnvborder; h -= 2*display_cnvborder + table_totaly;
canvas = new textCanvas((wxWindow*)this, display_cnvborder, display_cnvborder + table_totaly, w, h);
canvas->setData(mf, baseType, baseSize);
// Need to init these before calling EstimateCellSize()
sxText = NULL; syText = NULL;
// Try to make a good guess about the default table width
canvas->setNumberBase(numberBase);
EstimateCellSize(stepx, stepy);
sxText = new rviewText(ctrlPanel, stepx);
syText = new rviewText(ctrlPanel, stepy);
csBox = new rviewCheckBox(ctrlPanel);
csBox->SetValue(cosys);
// Init projection string
b = projString;
b += sprintf(b, "*:*");
if (dimMDD>1)
{
b += sprintf(b, ", *:*");
}
for (i=2; iSetValue(projString);
scrollx = -1; scrolly = -1;
newProjection();
setModeDimension((dimMDD == 1) ? 1 : 2);
setMinimumViewerSize(table_minwidth, table_minheight);
}
int rviewTable::openViewer(void)
{
RMDBGONCE(3, RMDebug::module_applications, "rviewTable", "openViewer()");
if (rviewDisplay::openViewer() == 0)
{
int w, h;
wxMenu *men;
char buffer[STRINGSIZE];
GetClientSize(&w, &h);
men = new wxMenu;
men->Append(MENU_TABLE_MODE_DECIMAL, "", NULL, TRUE);
men->Append(MENU_TABLE_MODE_OCTAL, "", NULL, TRUE);
men->Append(MENU_TABLE_MODE_HEX, "", NULL, TRUE);
sprintf(buffer, "&%s\n", lman->lookup("menTabMode"));
mBar->Append(men, buffer);
checkModeMenu();
label();
frameWidth=-1;
frameHeight=-1;
OnSize(w, h);
OnSize(w, h);
Show(TRUE);
return 0;
}
return -1;
}
void rviewTable::checkModeMenu(void)
{
switch (numberBase)
{
case 8: lastMode = MENU_TABLE_MODE_OCTAL; break;
case 16: lastMode = MENU_TABLE_MODE_HEX; break;
default: lastMode = MENU_TABLE_MODE_DECIMAL; break;
}
mBar->Check(lastMode, TRUE);
}
const char *rviewTable::getFrameName(void) const
{
return "rviewTable";
}
rviewFrameType rviewTable::getFrameType(void) const
{
return rviewFrameTypeTable;
}
int rviewTable::getViewerType(void) const
{
return RVIEW_RESDISP_TABLE;
}
void rviewTable::EstimateCellSize(int &width, int &height)
{
int w, h;
char buffer[STRINGSIZE];
canvas->EstimateCellSize(w, h);
// If prefs specify defaults (<= 0), update width/height, otherwise leave old values.
if (prefs->tableStepx <= 0)
{
width = w;
if (sxText != NULL) {sprintf(buffer, "%d", w); sxText->SetValue(buffer);}
}
if (prefs->tableStepy <= 0)
{
height = h;
if (syText != NULL) {sprintf(buffer, "%d", h); syText->SetValue(buffer);}
}
}
rviewTable::~rviewTable(void)
{
RMDBGONCE(3, RMDebug::module_applications, "rviewTable", "~rviewTable()");
closeViewer();
}
void rviewTable::label(void)
{
setDisplayTitle(lman->lookup("titleTable"));
sxText->SetLabel(lman->lookup("textStepx"));
syText->SetLabel(lman->lookup("textStepy"));
csBox->SetLabel(lman->lookup("textCosys"));
mBar->SetLabelTop(fixedNumberOfMenus, lman->lookup("menTabMode"));
mBar->SetLabel(MENU_TABLE_MODE_DECIMAL, lman->lookup("menTabModeDec"));
mBar->SetLabel(MENU_TABLE_MODE_OCTAL, lman->lookup("menTabModeOct"));
mBar->SetLabel(MENU_TABLE_MODE_HEX, lman->lookup("menTabModeHex"));
rviewDisplay::label();
}
void rviewTable::OnSize(int w, int h)
{
int x, y, i, j;
GetClientSize(&x, &y);
x -= 2*display_border;
i = x - 2*table_twidth - table_cwidth;
j = 2*display_border + display_cheight;
sxText->SetSize(display_border + i/6, j, table_twidth, table_theight);
syText->SetSize(display_border + (3*i)/6 + table_twidth, j, table_twidth, table_theight);
csBox->SetSize(display_border + (5*i)/6 + 2*table_twidth, j, table_cwidth, table_cheight);
y -= 2*display_border + table_totaly;
canvas->SetSize(display_border, display_border + table_totaly, x, y);
rviewDisplay::OnSize(w, h);
}
void rviewTable::OnMenuCommand(int id)
{
int newBase;
switch (id)
{
case MENU_TABLE_MODE_DECIMAL: newBase = 10; break;
case MENU_TABLE_MODE_OCTAL: newBase = 8; break;
case MENU_TABLE_MODE_HEX: newBase = 16; break;
default: newBase = -1; break;
}
if (newBase > 0)
{
mBar->Check(lastMode, FALSE);
numberBase = newBase;
checkModeMenu();
canvas->setNumberBase(numberBase);
EstimateCellSize(stepx, stepy);
newTableSize();
}
else
{
rviewDisplay::OnMenuCommand(id);
}
}
int rviewTable::process(wxObject &obj, wxEvent &evt)
{
int type = evt.GetEventType();
int i, j;
if (((&obj == (wxObject*)sxText) || (&obj == (wxObject*)syText)) && (type == wxEVENT_TYPE_TEXT_ENTER_COMMAND))
{
i = atoi(sxText->GetValue());
j = atoi(syText->GetValue());
if ((i > 0) && (j > 0))
{
stepx = i; stepy = j;
newTableSize();
return 1;
}
}
if ((&obj == (wxObject*)csBox) && (type == wxEVENT_TYPE_CHECKBOX_COMMAND))
{
cosys = csBox->GetValue();
newProjection();
return 1;
}
if (rviewDisplay::process(obj, evt) != 0)
{
return 1;
}
return 0;
}
int rviewTable::newProjection(void)
{
int dim1, dim2;
mapIndex = r_Point(dimMDD);
if (rviewParseProjection(getVirtualDomain(), pt1, pt2, projString, &freeDims, &mapIndex) != dimMDD)
{
rviewErrorbox::reportError(lman->lookup("errorProjection"), rviewTable::getFrameName(), "newProjection");
return -1;
}
for (dim1=0; dim1= dimMDD)
{
rviewErrorbox::reportError(lman->lookup("errorProjectFree"), rviewTable::getFrameName(), "newProjection");
return -1;
}
dim1 = mapIndex[dim1];
canvas->setProjection(pt1, pt2, freeDims, &mapIndex);
fieldsx = pt2[dim1] - pt1[dim1] + 1;
if (dim2 >= dimMDD)
{
fieldsy = 1;
}
else
{
dim2 = mapIndex[dim2];
fieldsy = pt2[dim2] - pt1[dim2] + 1;
}
//EstimateCellSize(&stepx, &stepy);
newTableSize();
return 0;
}
void rviewTable::newTableSize(void)
{
int cl, ct;
int newstepx, newstepy;
canvas->setStep(stepx, stepy);
canvas->setCoSys(cosys, cl, ct);
if (scrollx >= 0)
scrollx = canvas->GetScrollPos(wxHORIZONTAL);
else
scrollx = 0;
if (scrolly >= 0)
scrolly = canvas->GetScrollPos(wxVERTICAL);
else
scrolly = 0;
newstepx = (int)((fieldsx*stepx + 2*display_border + cl + display_scrstep - 1) / display_scrstep);
newstepy = (int)((fieldsy*stepy + 2*display_border + ct + display_scrstep - 1) / display_scrstep);
canvas->SetScrollbars(display_scrstep, display_scrstep, newstepx, newstepy, display_pgstep, display_pgstep, scrollx, scrolly);
}
int rviewTable::saveView(FILE *fp)
{
int status = rviewDisplay::saveView(fp);
long lvals[2];
lvals[0] = (long)stepx; lvals[1] = (long)stepy;
writeViewParam(fp, view_StepSize, 2, lvals);
lvals[0] = (long)(canvas->GetScrollPos(wxHORIZONTAL));
lvals[1] = (long)(canvas->GetScrollPos(wxVERTICAL));
writeViewParam(fp, view_ScrollPos, 2, lvals);
writeViewParam(fp, view_CoSys, (long)cosys);
writeViewParam(fp, view_NumBase, (long)numberBase);
return status;
}
int rviewTable::readView(const char *key, const char *value)
{
int status = rviewDisplay::readView(key, value);
if (status == 0)
{
if (strcmp(key, view_StepSize) == 0)
{
long lvals[2];
if (readVector(value, 2, lvals) == 0)
{
stepx = (int)lvals[0]; stepy = (int)lvals[1];
}
return 1;
}
else if (strcmp(key, view_ScrollPos) == 0)
{
long lvals[2];
if (readVector(value, 2, lvals) == 0)
{
scrollx = (int)lvals[0]; scrolly = (int)lvals[1];
}
return 1;
}
else if (strcmp(key, view_CoSys) == 0)
{
cosys = (bool)atoi(value);
return 1;
}
else if (strcmp(key, view_NumBase) == 0)
{
numberBase = atoi(value);
return 1;
}
return 0;
}
return status;
}
void rviewTable::loadViewFinished(void)
{
sxText->SetValue(stepx);
syText->SetValue(stepy);
csBox->SetValue(cosys);
mBar->Check(lastMode, FALSE);
checkModeMenu();
canvas->SetScrollPos(wxHORIZONTAL, scrollx);
canvas->SetScrollPos(wxVERTICAL, scrolly);
}