//----------------------------------------------------------------------------//
// module FVarTypes.cpp //
// //
// Dialog (form to be shown with ShowModal()) to show and edit the //
// variable types. Symbolic variables can be toggled between nominal //
// and nominal (symbolic) type. Additional information like extrema, //
// # symbols etc. is displayed for each variable. //
// //
// copyright (c) 2003 by Lars Haendel //
// home: www.newty.de //
// //
// This program is free software and can be used under the terms of the //
// GNU licence. See header file for further information and disclaimer. //
// //
//----------------------------------------------------------------------------//
#include <vcl.h>
#pragma hdrstop
#include "FVartypes.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
#include <htmlhelp> // due to HTML help
#define PREC 2 // precision used to display data minima etc.
TFVarTypes *FVarTypes;
//----------------------------------------------------------------------------------------------------------------------
// fill string grid with variable informatiob like extrema, # symbols and current variable type. Each variable is
// displayed in an own row.
void __fastcall TFVarTypes::FormShow(TObject *Sender)
{
// ToDo: check if data is given, else show IPI error and close
// a) set string grid properties
StringGrid->RowCount = data->nVar()+1; // set as many rows as variables (+1 because of the header row)
StringGrid->ColCount = 7;
StringGrid->Hint = "You may toggle the type of each highlighted variable by just clicking on it.";
// b) set column names and focused control
StringGrid->Cells[0][0] = "Column";
StringGrid->Cells[1][0] = "Minimum";
StringGrid->Cells[2][0] = "Maximum";
StringGrid->Cells[3][0] = "Mean";
StringGrid->Cells[4][0] = "Deviation";
StringGrid->Cells[5][0] = "# Symbols";
StringGrid->Cells[6][0] = "Type";
// c) set extrema, deviation etc.
char text[256];
for(int j=0;j<data->nVar();j++)
{
// column Id and - for first (output) add "(Output)"
if(j==0)
StringGrid->Cells[0][j+1] = AnsiString(TData::OriginalColumnInFile(j, data->OutputColumn())) + " (Output)";
else
StringGrid->Cells[0][j+1] = TData::OriginalColumnInFile(j, data->OutputColumn());
StringGrid->Cells[1][j+1] = ValueToText1(data->Min()[j], 0, PREC); // minimum
StringGrid->Cells[2][j+1] = ValueToText1(data->Max()[j], 0, PREC); // maximum
StringGrid->Cells[3][j+1] = ValueToText1(data->Mean()[j], 0, PREC); // mean
StringGrid->Cells[4][j+1] = ValueToText1(data->Dev()[j], 0, PREC); // deviation
StringGrid->Cells[5][j+1] = ValueToText1(data->nIntegerMaxMin(j), 0, PREC); // # symbols
}
// d) write variable types and initialize check box
VarTypesToStringGrid();
EvVarTypes();
}
//----------------------------------------------------------------------------------------------------------------------
// resize column width in string grid
void __fastcall TFVarTypes::FormResize(TObject *Sender)
{
// calculate column width ignoring the first column
const int w = (StringGrid->ClientWidth-StringGrid->ColWidths[0]-GetSystemMetrics(SM_CXVSCROLL))/(StringGrid->ColCount-1);
for(int j=1;j<StringGrid->ColCount;j++) // do not(!) resize the first column (variable id's)
StringGrid->ColWidths[j] = w;
}
//----------------------------------------------------------------------------------------------------------------------
// response to button 'Ok': close window
void __fastcall TFVarTypes::BtOkClick(TObject *Sender)
{
Close();
}
//----------------------------------------------------------------------------------------------------------------------
// if there are integer variables and they are not all symbolic: enable and uncheck check box
bool TFVarTypes::EvVarTypes()
{
// check variable's which could be symbolic are all symbolic (nominal)
bool f_Symbolic=false, f_AllSymbolic=true, f_AllContinous=true;
for(int j=0;j<data->nVar();j++)
if(prj->CouldBeSymbolic(j)) // variable type could be symbolic (nominal)
{
f_Symbolic = true; // there are possible symbolic variables
if(!data->IsSymbolic(j)) // check
f_AllSymbolic = false; // not all possibly symbolic are symbolic
else
f_AllContinous = false; // at least one variable is symbolic
}
// check/uncheck check box (group box 'Speed Settings')
CbNominal->Checked = f_AllSymbolic && f_Symbolic;
CbContinous->Checked = f_AllContinous;
if(f_Symbolic)
{
CbNominal ->Enabled = !f_AllSymbolic;
CbContinous->Enabled = !f_AllContinous;
}
else
{
CbNominal->Enabled = false;
CbContinous->Enabled = false;
}
return f_Symbolic;
}
//----------------------------------------------------------------------------------------------------------------------
// write all variable types to string grid
void TFVarTypes::VarTypesToStringGrid()
{
for(int j=0;j<data->nVar();j++) // for each variable
switch(data->GetVarType(j)) // get variable type ...
{
case TData::cont : StringGrid->Cells[6][j+1]="continous"; break; // .. and write corresponding text
case TData::symb : StringGrid->Cells[6][j+1]="symbolic"; break;
}
}
//----------------------------------------------------------------------------------------------------------------------
// evaluate mouse clicks in the string grid: toggle symbolic variable type between nominal and ordinal type. Display
// warning if variable is continous
void __fastcall TFVarTypes::StringGridClick(TObject *Sender)
{
// a) only evaluate clicks in the 6th column which contains the variable types
if(StringGrid->Col!=6)
return;
// b) if 6th column: try to toggle variable type
if(prj->CouldBeSymbolic(StringGrid->Row-1)) // if variable could be symbolic (nominal)
{
// b1) if it is an input variable ...
if(StringGrid->Row!=1)
if(!main->AllowChangeOfInputType()) // ... ask user if a model is present cause this would be deleted
{
CorrectSelection();
return;
}
// b2) toggle variable type
if(data->GetVarType(StringGrid->Row-1)==TData::symb)
{
data->SetVarType(StringGrid->Row-1, TData::cont); // set to be continous
StringGrid->Cells[6][StringGrid->Row]="continous";
}
else
{
data->SetVarType(StringGrid->Row-1, TData::symb); // set to be symbolic (nominal)
StringGrid->Cells[6][StringGrid->Row]="symbolic";
}
// b3) display warning if output variable type has been changed
if(StringGrid->Row==1)
Application->MessageBox("You've toggled the type of the output variable! This type is ignored.\nUse the regression check\
box instead!", "Warning", MB_OK | MB_ICONWARNING);
// b4) check/unckeck boxes
EvVarTypes(); // if all symbolic variables are either nominal or ordinal: check corresponding check box
main->SetSavedFlag(false); // unset saved flag cause something was changed
}
// c) 'correct selection'
CorrectSelection();
}
//----------------------------------------------------------------------------------------------------------------------
// correct selection in list box
void TFVarTypes::CorrectSelection()
{
// (hack!) necessary cause focus is always defered to close button ??
TGridRect rect;
rect.Left = rect.Right = rect.Top = rect.Bottom = 1;
StringGrid->Selection=rect;
}
//----------------------------------------------------------------------------------------------------------------------
// if box is checked: set all symbolic variables to be nominal
void __fastcall TFVarTypes::CbNominalClick(TObject *Sender)
{
if(CbNominal->Checked) // if check box is set
{
// determine if any input variable would be changed
bool f_Check = false;
for(int j=1;j<data->nVar();j++)
if(prj->CouldBeSymbolic(j) && !data->IsSymbolic(j)) // if variable could be symbolic and currently is not ...
f_Check = true; // ... set flag that an input variable would be changed
// if model is present: ask user if inputs would be changed
if(f_Check)
if(!main->AllowChangeOfInputType())
{
CbNominal->Checked=false; // reset again
return;
}
// change
for(int j=0;j<data->nVar();j++) // for each variable
if(prj->CouldBeSymbolic(j)) // set it to be symbolic if it could
data->SetVarType(j, TData::symb);
CbNominal->Enabled = false; // disable myself
CbContinous->Enabled = true; // and enable
CbContinous->Checked = false; // and uncheck the 'other'
// display changes: write variable types to list box again
VarTypesToStringGrid();
}
ActiveControl = BtOk; // set focus to button 'Ok'
}
//----------------------------------------------------------------------------------------------------------------------
// if box is checked: set all symbolic variables to be continous
void __fastcall TFVarTypes::CbContinousClick(TObject *Sender)
{
if(CbContinous->Checked) // if check box is set
{
// determine if any input(!) variable would be changed
bool f_Check = false;
for(int j=1;j<data->nVar();j++)
if(data->IsSymbolic(j)) // if variable is symbolic
f_Check = true; // ... set flag that an input variable would be changed
// if model is present: ask user if inputs would be changed
if(f_Check)
if(!main->AllowChangeOfInputType())
{
CbContinous->Checked=false; // reset again
return;
}
// change
for(int j=0;j<data->nVar();j++) // for each variable
data->SetVarType(j, TData::cont); // set it to be continous
CbContinous->Enabled = false; // disable myself
CbNominal->Enabled = true; // and enable
CbNominal->Checked = false; // and uncheck the 'other'
// display changes: write variable types to list box again
VarTypesToStringGrid();
}
ActiveControl = BtOk; // set focus to button 'Ok'
}
//----------------------------------------------------------------------------------------------------------------------
// ensure that only integer input variable types can be selected
void __fastcall TFVarTypes::StringGridSelectCell(TObject *Sender, int ACol, int ARow, bool &CanSelect)
{
CanSelect = (ACol==6 /*&& ARow!=1*/ && prj->CouldBeSymbolic(ARow-1));
}
//----------------------------------------------------------------------------------------------------------------------
// Respond to OnDrawCell event: draw cell text using some special background colors to visualize variable types
void __fastcall TFVarTypes::StringGridDrawCell(TObject* Sender, int ACol, int ARow, TRect& Rect, TGridDrawState State)
{
// if it's a fixed row (headers)
if(State.Contains(gdFixed))
{
StringGrid->Canvas->Brush->Color = clBtnFace;
StringGrid->Canvas->Font->Color = clWindowText;
StringGrid->Canvas->FillRect(Rect);
Frame3D(StringGrid->Canvas, Rect, clBtnHighlight, clBtnShadow, 1);
}
// color column 6 if it could be a symbolic variable (if it would be an input)
else if(ACol==6 /*&& ARow!=1*/ && prj->CouldBeSymbolic(ARow-1)) // note: minus 1 because first row is 1
{
if(data->GetVarType(ARow-1)==TData::cont)
StringGrid->Canvas->Brush->Color = clActiveCaption;
else
StringGrid->Canvas->Brush->Color = clInactiveCaption;
StringGrid->Canvas->Font->Color = clCaptionText;
StringGrid->Canvas->FillRect(Rect);
}
// if normal
else
{
StringGrid->Canvas->Brush->Color = StringGrid->Color;
StringGrid->Canvas->Font->Color = StringGrid->Font->Color;
StringGrid->Canvas->FillRect(Rect);
}
AnsiString text = " " + StringGrid->Cells[ACol][ARow];
StringGrid->Canvas->TextRect(Rect, Rect.Left, Rect.Top, text);
}
//----------------------------------------------------------------------------------------------------------------------
// close all help windows
void __fastcall TFVarTypes::FormClose(TObject*, TCloseAction&){ /* HtmlHelp(0, 0, HH_CLOSE_ALL, 0); */}