static const char* szModule = "FEditSets.cpp";
//----------------------------------------------------------------------------//
// module FEditSets.cpp //
// //
// Form to edit the parameter sets for the parameter tuning //
// //
// 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
#pragma package(smart_init)
#pragma resource "*.dfm"
#include <htmlhelp> // due to HTML help
//----------------------------------------------------------------------------------------------------------------------
#include "FEditSets.h"
#include "para.h" // due to default parameters
#include "fileutil.h" // flag to string
#include "FMain.h" // TFMain
#define MAX_TASKS 20 // maximal # tasks
static char text[256];
int ParseParameters(const char*const& szPar, float*& para, const float& defVal, const char*const& szName
, const float& min, const bool f_Integer/*=false*/, const float& max/*=MAXFLOAT*/);
//----------------------------------------------------------------------------------------------------------------------
// check if parameter string is valid, else ask the user to restore defaults or to re-edit string
bool CheckParameterString(const bool& f_OnlyOne, AnsiString& szPara, const AnsiString& szName, const float& defVal,
const float& min, const bool& f_Integer, const float& max)
{
AnsiString szErrText = "Error in parameter '" + szName + "'"; // compose message box caption
bool f_restore=false; // flag: restore default value
float* para; // dummy parameter array, needed for ParseParameters(), will be deleted afterwards
try{
ParseParameters(szPara.c_str(), para, -1, szName.c_str(), min, f_Integer, max);} // parse
catch(TExceptionU excp) // error handling
{
sprintf(text, "%s Use default value?", excp.GetErrorText()); // compose error text
// ask user to use defaults or to try again
if(Application->MessageBox(text, szErrText.c_str(), MB_YESNO | MB_ICONERROR)== ID_YES)
f_restore = true; // set restore flag
else
{
delete[] para; // try again ...
return true; // keep focus
}
}
// if the string is empty, i.e. does not contain any parameter ... display error message and set restore flag
if(szPara.IsEmpty()){
// message: no parameter specified: using defaults
Application->MessageBox("No parameter(s) specified! Using default value!", szErrText.c_str(), MB_OK|MB_ICONERROR);
f_restore = true;}
// if flag is set ... restore default value
const bool f_boolean = (f_Integer && min==0 && max==1);
if(f_restore)
if(f_boolean && !f_OnlyOne) // default value is boolean ...
szPara = FlagToString(defVal); // ... initialize string with 'true' ore 'false'
else
szPara = ValueToText1(defVal, 0, PREC_PARA); // else: set default value
// if parameter is 'true' or 'false' -> change to '0/1' if 'f_OnlyOne' is set
if(f_OnlyOne)
if(strcmp("true", szPara.c_str())==0)
szPara = 1;
else
if(strcmp("false", szPara.c_str())==0)
szPara = 0;
delete[] para; // release dummy parameter array
return f_restore; //
}
TFEditSets *FEditSets;
//----------------------------------------------------------------------------------------------------------------------
// initialize controls
void __fastcall TFEditSets::FormShow(TObject *Sender)
{
// pre-check
IfTrueThrowTypeA(!data, "No learn data object associated!", "TFEditSets::FormShow", szModule);
RbNormal->Checked = true; // initialize task wizard radio buttons
if(BtWizard->Enabled) // set focus ...
ActiveControl = BtWizard; // if possible to wizard button ...
else
ActiveControl = BtOk; // ... and else to Button 'Ok'
// a) disable/enable parameter edit fields and descriptions depending on task type (regression or classification)
ESigma->Visible = prj->Regression();
LaSigma->Visible = prj->Regression();
ESpecial->Visible = !prj->Regression();
LaSpecial->Visible = !prj->Regression();
EnableTaskEditing(CbEnableEditing->Checked); // enable/disable editing fields and buttons
// b) set column names in list view
LvTasks->Columns->Clear(); // clear all columns
LvTasks->Columns->Add()->Caption = "Task";
LvTasks->Columns->Add()->Caption = "Sets";
LvTasks->Columns->Add()->Caption = "Learn";
LvTasks->Columns->Add()->Caption = "Intervals";
LvTasks->Columns->Add()->Caption = "Anti COD";
LvTasks->Columns->Add()->Caption = "Eta";
LvTasks->Columns->Add()->Caption = "Min. rule mass";
if(prj->Regression())
LvTasks->Columns->Add()->Caption = "Sigma";
else
LvTasks->Columns->Add()->Caption = "Kernel width";
LvTasks->Columns->Add()->Caption = "Weights";
LvTasks->Columns->Add()->Caption = "Prune";
LvTasks->Columns->Add()->Caption = "Euclidean";
// set column width and enable auto sizing
int w = LvTasks->Width/LvTasks->Columns->Count; // width of each column
for(int i=0;i<LvTasks->Columns->Count;i++)
{
LvTasks->Columns->Items[i]->AutoSize = true;
LvTasks->Columns->Items[i]->Width = w;
}
// c) transfer tasks to task list view
LvTasks->Items->Clear(); // delete all
for(int i=0;i<prj->nTasks();i++) // for all tasks
AddTaskToListView(&(prj->GetTask(i)));
DisplaySetCount(); // ... and display it
SetDefaults(); // initialize parameters (edit task group box) with default values
f_SomethingChanged = false;
}
//----------------------------------------------------------------------------------------------------------------------
// response to button 'Ok': close window
void __fastcall TFEditSets::BtOkClick(TObject *Sender)
{
Close();
}
//----------------------------------------------------------------------------------------------------------------------
// check box 'Enable task editing' clicked:
void __fastcall TFEditSets::CbEnableEditingClick(TObject *Sender)
{
EnableTaskEditing(CbEnableEditing->Checked); // enable/disable editing fields and buttons
}
//----------------------------------------------------------------------------------------------------------------------
// enable/disable task editing
void TFEditSets::EnableTaskEditing(const bool& f_Enable)
{
// labels
LaIntervals ->Enabled = f_Enable && prj->Regression(); // enable only for regression tasks
LaWmin ->Enabled = f_Enable;
LaEta ->Enabled = f_Enable;
LaSpecial ->Enabled = f_Enable;
LaSigma ->Enabled = f_Enable;
LaCardinality->Enabled = f_Enable;
LaPrune ->Enabled = f_Enable;
LaWeights ->Enabled = f_Enable;
LaEuclidean ->Enabled = f_Enable;
// edit fields
EIntervals ->Enabled = f_Enable && prj->Regression(); // enable only for regression tasks
EWmin ->Enabled = f_Enable;
EEta ->Enabled = f_Enable;
ESpecial ->Enabled = f_Enable;
ESigma ->Enabled = f_Enable;
ECardinality->Enabled = f_Enable;
EPrune ->Enabled = f_Enable;
EWeights ->Enabled = f_Enable;
EEuclidean ->Enabled = f_Enable;
// buttons
BtDefaults->Enabled = f_Enable;
BtAccept ->Enabled = f_Enable;
BtEdit ->Enabled = f_Enable && LvTasks->Selected; // enable only if list item (task) is selected
BtDelete ->Enabled = f_Enable && LvTasks->Selected;
BtClearAll->Enabled = f_Enable && (LvTasks->Items->Count!=0); // enable only if list contains tasks
// wizard (disable if other controls get enabled)
RbFast ->Enabled = !f_Enable;
RbNormal ->Enabled = !f_Enable;
RbExhaustive->Enabled = !f_Enable;
BtWizard ->Enabled = !f_Enable;
}
//----------------------------------------------------------------------------------------------------------------------
// add given task to list view
void TFEditSets::AddTaskToListView(const TTask*const& task)
{
TListItem* item = LvTasks->Items->Add(); // add new list item
// copy parameter strings to list view
item->Caption = LvTasks->Items->Count; // task id
item->SubItems->Add(AnsiString(task->nSets)); // # runs (all)
item->SubItems->Add(AnsiString(task->nSetsLearn)); // # runs (learn)
item->SubItems->Add(task->szN_Int); // 'Intervals'
item->SubItems->Add(task->szW_COD); // 'w_COD'
item->SubItems->Add(task->szEta); // 'Eta'
item->SubItems->Add(task->szP_Min); // 'min. cuboid mass'
if(prj->Regression()) // type specific parameters
item->SubItems->Add(task->szSigma); // 'Sigma'
else
item->SubItems->Add(task->szW_Kernel); // kernel width
item->SubItems->Add(task->szWeights); // 'Use Weights'
item->SubItems->Add(task->szPrune); // 'Prune Cuboids'
item->SubItems->Add(task->szMetric); // 'Euclidean Distance'
f_SomethingChanged = true;
}
//----------------------------------------------------------------------------------------------------------------------
// initialize parameters (edit task group box) with default values
void TFEditSets::SetDefaults()
{
// other parameters
if(prj->Regression())
EIntervals->Text = ValueToText1(para->N_Int); // # output intervals
else
EIntervals->Text = ValueToText1(prj->nClasses()); // # classes
EWmin ->Text = ValueToText1(para->w_COD, 0, PREC_PARA); // w_COD
EEta ->Text = ValueToText1(para->Eta); // eta
ECardinality ->Text = ValueToText1(para->p_min); // min. cuboid mass
ESigma ->Text = ValueToText1(para->Sigma, 0, PREC_PARA); // sigma
ESpecial ->Text = ValueToText1(para->W_Kernel); // special (kernel width)
// boolean parameters: initialize check boxes
EWeights ->Text = FlagToString(para->Weights); // use weights
EPrune ->Text = FlagToString(para->Prune); // prune cuboids
EEuclidean->Text = FlagToString(para->Metric==2); // euclidean distance
}
//----------------------------------------------------------------------------------------------------------------------
// display total number of parameter sets
void TFEditSets::DisplaySetCount()
{
// display # runs
LaSetCount1->Caption = "You've defined " + AnsiString(prj->nParaSets()) + " parameter set(s).";
LaSetCount2->Caption = AnsiString(prj->nParaSetsLearn()) + " times must be learned!";
}
//----------------------------------------------------------------------------------------------------------------------
// call SetDefaults() which will initialize all parameters (edit task group box) with default values
void __fastcall TFEditSets::BtDefaultsClick(TObject *Sender){
SetDefaults();}
//----------------------------------------------------------------------------------------------------------------------
// enable buttons 'Edit' and 'Delete' (accepted tasks group box) if an list item (task) is selected
void __fastcall TFEditSets::LvTasksSelectItem(TObject*, TListItem*, bool Selected){
BtEdit ->Enabled = Selected && CbEnableEditing->Checked;
BtDelete->Enabled = Selected && CbEnableEditing->Checked;}
//----------------------------------------------------------------------------------------------------------------------
// initialize tasks using a heuristic approach
void __fastcall TFEditSets::BtWizardClick(TObject *Sender)
{
// a) initialize
DeleteAllTasks(); // delete all existing tasks
TTask task;
task.szSigma[0] = task.szW_Kernel[0] = '\0'; // terminate (eventually) unused parameter strings
// b) initialize task strings
//-------------------------------------------------------------------------------------------------------------------
// b1) fast
if(RbFast->Checked)
{
strcpy(task.szEta, "0.2"); // 'Eta'
float w1, w2, w3; // 'w_COD'
w2 = para->w_COD;
w1 = floor(0.5 + 10*w2*0.66)/10; // round to one digit precision
w3 = floor(0.5 + 10*w2*1.33)/10;
if(w2-w1 >= 0.6) // if values differ by at least 0.6 ...
{
strcpy(task.szW_COD, ValueToText1(w1, 0, PREC_PARA)); // ... copy first value and ...
strcat(task.szW_COD, " ");
strcat(task.szW_COD, ValueToText1(w2, 0, PREC_PARA)); // ... add 2nd value and ...
if(w3 <= Max_w_COD(data))
{
strcat(task.szW_COD, " ");
strcat(task.szW_COD, ValueToText1(w3, 0, PREC_PARA)); // ... add third value if it's not to high
}
}
else
strcpy(task.szW_COD, ValueToText1(w2, 0, PREC_PARA)); // else: use only 2nd value
if(prj->Regression())
{
strcpy(task.szN_Int, "10 15"); // 'Intervals' (regression)
strcpy(task.szSigma, "0.001"); // 'Sigma'
}
else
{
sprintf(task.szN_Int, "%d", prj->nClasses()); // 'Intervals' (classification)
strcpy(task.szW_Kernel, "1 3"); // kernel width
}
strcpy(task.szP_Min, "2 4"); // 'min. cuboid mass'
strcpy(task.szPrune, "true"); // 'Prune Cuboids'
strcpy(task.szWeights, "true"); // 'Use Weights'
strcpy(task.szMetric, "1"); // 'Euclidean Distance'
}
//-------------------------------------------------------------------------------------------------------------------
// b2) normal
if(RbNormal->Checked)
{
strcpy(task.szEta, "0.2 0.5"); // 'Eta'
float w1, w2, w3; // 'w_COD'
w2 = para->w_COD;
w1 = floor(0.5 + 10*w2*0.66)/10; // round to one digit precision
w3 = floor(0.5 + 10*w2*1.33)/10;
if(w2-w1 >= 0.4) // if values differ by at least 0.4 ...
{
strcpy(task.szW_COD, ValueToText1(w1, 0, PREC_PARA)); // ... copy first value and ...
strcat(task.szW_COD, " ");
strcat(task.szW_COD, ValueToText1(w2, 0, PREC_PARA)); // ... add 2nd value and ...
if(w3 <= Max_w_COD(data))
{
strcat(task.szW_COD, " ");
strcat(task.szW_COD, ValueToText1(w3, 0, PREC_PARA)); // ... add third value if it's not to high
}
}
else
strcpy(task.szW_COD, ValueToText1(w2, 0, PREC_PARA)); // else: use only 2nd value
if(prj->Regression())
{
strcpy(task.szN_Int, "10 15"); // 'Intervals' (regression)
strcpy(task.szSigma, "0.001 0.01"); // 'Sigma'
}
else
{
sprintf(task.szN_Int, "%d", prj->nClasses()); // 'Intervals' (classification)
strcpy(task.szW_Kernel, "1 2 3"); // kernel width
}
strcpy(task.szP_Min, "2 4 7"); // 'min. cuboid mass'
strcpy(task.szPrune, "true false"); // 'Prune Cuboids'
strcpy(task.szWeights, "true"); // 'Use Weights'
strcpy(task.szMetric, "1"); // 'Euclidean Distance'
}
//-------------------------------------------------------------------------------------------------------------------
// b3) exhaustive
if(RbExhaustive->Checked)
{
strcpy(task.szEta, "0.2 0.5 0.7"); // 'Eta'
float w1, w2, w3, w4; // 'w_COD'
w3 = para->w_COD;
w1 = floor(0.5 + 10*w3*0.33)/10; // round to one digit precision
w2 = floor(0.5 + 10*w3*0.66)/10;
w4 = floor(0.5 + 10*w3*1.33)/10;
if(w3-w1 >= 0.4) // if values differ by at least 0.4 ...
{
strcpy(task.szW_COD, ValueToText1(w1, 0, PREC_PARA)); // ... copy first value and ...
strcat(task.szW_COD, " ");
strcat(task.szW_COD, ValueToText1(w2, 0, PREC_PARA)); // ... add 2nd value and ...
strcat(task.szW_COD, " ");
strcat(task.szW_COD, ValueToText1(w3, 0, PREC_PARA)); // ... add third value and ...
if(w3 <= Max_w_COD(data))
{
strcat(task.szW_COD, " ");
strcat(task.szW_COD, ValueToText1(w4, 0, PREC_PARA)); // ... add fourth value if it's not to high
}
}
else
strcpy(task.szW_COD, ValueToText1(w3, 0, PREC_PARA)); // else: use only third value
if(prj->Regression())
{
strcpy(task.szN_Int, "10 15 20"); // 'Intervals' (regression)
strcpy(task.szSigma, "0.001 0.01"); // 'Sigma'
}
else
{
sprintf(task.szN_Int, "%d", prj->nClasses()); // 'Intervals' (classification)
strcpy(task.szW_Kernel, "1 2 3"); // kernel width
}
strcpy(task.szP_Min, "2 4 7"); // 'min. cuboid mass'
strcpy(task.szPrune, "true false"); // 'Prune Cuboids'
strcpy(task.szWeights, "true false"); // 'Use Weights'
strcpy(task.szMetric, "1"); // 'Euclidean Distance'
}
// c) add new task to project
try
{
prj->AddTask(&task);
}
catch(TExceptionU excp)
{
Application->MessageBox(excp.GetErrorText(), "Error", MB_OK | MB_ICONERROR);
}
// d) add new task to list view
AddTaskToListView(&prj->GetTask(prj->nTasks()-1));
// e) reset parameter strings and display actualized # parameter sets
SetDefaults();
DisplaySetCount();
ActiveControl = BtOk; // set focus to button 'Ok'
}
//----------------------------------------------------------------------------------------------------------------------
// button 'Clear All' clicked: ask user and delete all tasks from list
void __fastcall TFEditSets::BtClearAllClick(TObject *Sender)
{
// ask
if(!f_DisableQuestions)
if(Application->MessageBox("Clear all tasks ??", "Question", MB_YESNO | MB_ICONQUESTION)==ID_NO)
return;
DeleteAllTasks();
// disable buttons
BtClearAll->Enabled = false;
BtDelete ->Enabled = false; // 'Delete'
BtEdit ->Enabled = false; // 'Edit'
}
//----------------------------------------------------------------------------------------------------------------------
// functions gets called if the one of the parameter edit boxes (TEdit) exits focus: check if actual parameter string
// is valid using function CheckParameterString()
// note: the steps are always the same: a) buffer text, b) check text, c) eventually give focud back and d) write back
void __fastcall TFEditSets::EIntervalsExit(TObject *Sender){ // 'Intervals'
AnsiString tmp = EIntervals->Text;
if(CheckParameterString(false, tmp, LaIntervals->Caption, para->N_Int, MIN_N_INT, INT_N_INT, MAX_N_INT))
ActiveControl = EIntervals;
EIntervals->Text = tmp;}
void __fastcall TFEditSets::EWminExit(TObject *Sender){ // 'w_min'
AnsiString tmp = EWmin->Text;
if(CheckParameterString(false, tmp, LaWmin->Caption, para->w_COD, MIN_W_COD, INT_W_COD, Max_w_COD(data)))
ActiveControl = EWmin;
EWmin->Text = tmp;}
void __fastcall TFEditSets::EEtaExit(TObject *Sender){ // 'Eta'
AnsiString tmp = EEta->Text;
if(CheckParameterString(false, tmp, LaEta->Caption, para->Eta, MIN_ETA, INT_ETA, MAX_ETA))
ActiveControl = EEta;
EEta->Text = tmp;}
void __fastcall TFEditSets::ECardinalityExit(TObject *Sender){ // 'min. cuboid mass'
AnsiString tmp = ECardinality->Text;
if(CheckParameterString(false, tmp, LaCardinality->Caption, para->p_min, MIN_P_MIN, INT_P_MIN, Max_P_Min(data)))
ActiveControl = ECardinality;
ECardinality->Text = tmp;}
void __fastcall TFEditSets::ESigmaExit(TObject *Sender){ // 'Sigma'
AnsiString tmp = ESigma->Text;
if(CheckParameterString(false, tmp, LaSigma->Caption, para->Sigma, MIN_SIGMA, INT_SIGMA, MAX_SIGMA))
ActiveControl = ESigma;
ESigma->Text = tmp;}
void __fastcall TFEditSets::ESpecialExit(TObject *Sender){ // 'Special'
AnsiString tmp = ESpecial->Text;
if(CheckParameterString(false, tmp, LaSpecial->Caption, para->W_Kernel, MIN_W_KERNEL, INT_W_KERNEL, MAX_W_KERNEL))
ActiveControl = ESpecial;
ESpecial->Text = tmp;}
void __fastcall TFEditSets::EWeightsExit(TObject *Sender){ // 'Use Weights'
AnsiString tmp = EWeights->Text;
if(CheckParameterString(false, tmp, LaWeights->Caption, para->Weights, MIN_WEIGHTS, INT_WEIGHTS, MAX_WEIGHTS))
ActiveControl = EWeights;
EWeights->Text = tmp;}
void __fastcall TFEditSets::EPruneExit(TObject *Sender){ // 'Prune Cuboids'
AnsiString tmp = EPrune->Text;
if(CheckParameterString(false, tmp, LaPrune->Caption, para->Prune, MIN_PRUNE, INT_PRUNE, MAX_PRUNE))
ActiveControl = EPrune;
EPrune->Text = tmp;}
void __fastcall TFEditSets::EEuclideanExit(TObject *Sender){ // 'Euclidean Distance'
AnsiString tmp = EEuclidean->Text;
bool euclid = (para->Metric==2);
if(CheckParameterString(false, tmp, LaEuclidean->Caption, euclid, 0, 1, 1))
ActiveControl = EEuclidean;
EEuclidean->Text = tmp;}
//----------------------------------------------------------------------------------------------------------------------
// button 'Add Task' clicked: add current task to list and reset parameters to default
void __fastcall TFEditSets::BtAcceptClick(TObject *Sender)
{
// a) check if maximum n- umber of tasks is exceeded
if(LvTasks->Items->Count>=MAX_TASKS)
{
sprintf(text, "Too many task! The maximum number of tasks is %d. Cannot add any more!", MAX_TASKS);
Application->MessageBox(text, "Error! Action aborted!", MB_OK | MB_ICONERROR);
return;
}
// copy parameter strings to list
TTask task;
strcpy(task.szN_Int, EIntervals->Text.c_str()); // 'Intervals'
strcpy(task.szEta, EEta->Text.c_str()); // 'Eta'
strcpy(task.szW_COD, EWmin->Text.c_str()); // 'w_COD'
strcpy(task.szSigma, ESigma->Text.c_str()); // 'Sigma'
strcpy(task.szW_Kernel, ESpecial->Text.c_str()); // kernel width
strcpy(task.szP_Min, ECardinality->Text.c_str()); // 'min. cuboid mass'
strcpy(task.szPrune, EPrune->Text.c_str()); // 'Prune Cuboids'
strcpy(task.szWeights, EWeights->Text.c_str()); // 'Use Weights'
// 'Euclidean Distance'
// note: map, as parameter is entered as 'true' (1) or 'false' (0) and it is needed as '2' and '1' in TTask
float* par = new float[12];
int nPar = ParseParameters(EEuclidean->Text.c_str(), par, 1, "Metric (intern)", 0);
if(nPar==1)
sprintf(task.szMetric, "%.0f", ++par[0]);
else
sprintf(task.szMetric, "%.0f;%.0f", ++par[0], ++par[1]);
// add new task to project
try
{
prj->AddTask(&task);
}
catch(TExceptionU excp)
{
Application->MessageBox(excp.GetErrorText(), "Error", MB_OK | MB_ICONERROR);
}
// and add task to list view
AddTaskToListView(&prj->GetTask(prj->nTasks()-1));
// e) reset parameter strings and display actualized # parameter sets
SetDefaults();
DisplaySetCount();
BtClearAll->Enabled = true;
}
//----------------------------------------------------------------------------------------------------------------------
// delete key: forward to BtDeleteClick()
void __fastcall TFEditSets::LvTasksKeyUp(TObject *Sender, WORD &Key, TShiftState Shift){
if(Key==VK_DELETE)
BtDeleteClick(this);}
//----------------------------------------------------------------------------------------------------------------------
// button 'Delete' clicked: ask user and delete task from list
void __fastcall TFEditSets::BtDeleteClick(TObject *Sender)
{
// a) get selected item and it's index, return if none is selected
TListItem* item = LvTasks->Selected;
if(!item)
return;
const int index = LvTasks->Items->IndexOf(item);
// b) ask user if he really wants to delete task
if(!f_DisableQuestions)
{
AnsiString text = "Delete task " + AnsiString(index+1) + " from list?? The other tasks will be re-numbered.";
if(Application->MessageBox(text.c_str(), "Question", MB_YESNO | MB_ICONQUESTION)!=ID_YES)
return;
}
// c) delete
DeleteTask(index);
}
//----------------------------------------------------------------------------------------------------------------------
// delete all tasks from list
void TFEditSets::DeleteAllTasks()
{
LvTasks->Items->Clear(); // delete list view
prj->DeleteAllTasks(); // delete in project (TProjectG) object
DisplaySetCount(); // display actualized # sets
}
//----------------------------------------------------------------------------------------------------------------------
// delete task from list
void TFEditSets::DeleteTask(const int& index)
{
// a) delete from listview and disable buttons 'Delete' and 'Edit'
LvTasks->Items->Delete(index); // delete
BtDelete->Enabled = false; // disable buttons 'Delete' and 'Edit'
BtEdit ->Enabled = false;
if(LvTasks->Items->Count==0) // disable 'Clear All' button if task list is empty
BtClearAll->Enabled = false;
// correct task Id's
for(int i=0;i<LvTasks->Items->Count;i++)
LvTasks->Items->Item[i]->Caption = i+1;
// delete from project
prj->DeleteTask(index);
// display actualized # sets
DisplaySetCount();
f_SomethingChanged = true;
}
//----------------------------------------------------------------------------------------------------------------------
// buttin 'Edit' clicked: delete selected task from list and copy it back to the parameter strings (edit task group box)
void __fastcall TFEditSets::BtEditClick(TObject *Sender)
{
// a) get selected file and it's index, return if none is selected
TListItem* item = LvTasks->Selected;
if(!item)
return;
const int index = LvTasks->Items->IndexOf(item);
// b) ask user
if(!f_DisableQuestions)
{
AnsiString text = "Move task " + AnsiString(index+1) + " back to the editing enviroment ??\n\
The other tasks will be re-numbered.";
if(Application->MessageBox(text.c_str(), "Question", MB_YESNO | MB_ICONQUESTION)!=ID_YES)
return;
}
// c) copy to parameter strings
const TTask& task = prj->GetTask(index);
EIntervals ->Text = task.szN_Int; // # output intervals
EWmin ->Text = task.szW_COD; // w_COD
EEta ->Text = task.szEta; // eta
ESigma ->Text = task.szSigma; // sigma
ESpecial ->Text = task.szW_Kernel; // special (kernel width)
ECardinality->Text = task.szP_Min; // min. cuboid mass
// boolean parameters
EPrune ->Text = task.szPrune; // prune cuboids
EWeights->Text = task.szWeights; // use weights
int i=0, nPara=0;
char szText[256];
szText[0]='\0';
while(task.szMetric[i]!='\0')
{
if(task.szMetric[i]=='1')
{
strcat(szText, "false");
nPara++;
}
else
if(task.szMetric[i]=='2')
{
if(nPara>0)
strcat(szText, ";");
strcat(szText, "true");
nPara++;
}
i++;
}
EEuclidean->Text = szText; // euclidean distance
// d) delete from list view and project
DeleteTask(index);
}