Board index » cppbuilder » Re: TDrawGrid or week palnner alternative...

Re: TDrawGrid or week palnner alternative...


2007-07-25 07:10:59 AM
cppbuilder70
"Mike Collins" <its@TheBottomOfThePost>wrote:
Quote

[...] I need some sort of control that can represent a week
in hour blocks.
And right after you accomplish that, they'll want to look at
a month at a time and historically as well.
Quote
[...] I have tried to mock up the same functionality using
a string grid but i failed to make it allow me to make
multiple selections.
I don't see anything in your requirements that wold make me
think of any other control other than a TStringGrid.
Of course, you'd need to set it's DefaultDrawing property to
false and add an OnDrawCell event but that's nothing. The rest
is design choices.
Quote
i have a set of categories and i need to drop them onto a
grid that represents a week.
Do not limit the columns and rows to represent the week
precisely. You can turn off the grid lines and then draw
them yourself when you detect a line is needed or you can
erase the unwanted lines by expanding the Rect parameter in
the OnDrawCell event (only erase or draw the bottom and right -
the top and left are drawn by other cells).
This way, you can have a seperate cell for each activity
and use TStringGrid methods such as MouseToCell to know when
the user double-clicks or right-clicks (design choice) a
particulare activity.
With seperate cells for each activity, you can use the Objects
property to point to a TActivity struct that will contain all
of the information needed for painting the cell in the
OnDrawCell which includes a ACol and ARow parameter that can
be used to index into the Objects[][].
When an Activity is dropped onto a cell, popup a captionless
modal form with some defaults set and have the user fill-in
the blanks. If the user double-clicks (or right-clicks), popup
the same modal form so that the TActivity can be edited.
You'll also most likely want to (at a minimum) use a cracker
class so that you can utilize MoveRow, InsertRow and DeleteRow.
For example:
//------------------------------------------------------------
class TMyStringGrid : public TStringGrid
{
public:
void __fastcall MoveRow(int FromIndex, int ToIndex)
{
inherited::MoveRow(FromIndex,ToIndex);
}
void __fastcall InsertRow(int Index )
{
++RowCount;
inherited::MoveRow( RowCount-1, Index );
}
void __fastcall DeleteRow(int Index)
{
inherited::DeleteRow(Index);
}
};
//------------------------------------------------------------
Then you can access these 3 methods like this:
// This will move row 4 to row 1 and push everything down
((TMyStringGrid*)StringGrid1)->MoveRow( 4, 1 );
// This will insert a new empty row at row 2 and push everything down:
((TMyStringGrid*)StringGrid1)->InsertRow( 2 );
// This will delete row 3 and move everything else up:
((TMyStringGrid*)StringGrid1)->DeleteRow( 3 );
~ JD
 
 

Re:Re: TDrawGrid or week palnner alternative...

Hi all, i have a user interface requirement that i'm struggling to fulfil.
I need some sort of control that can represent a week in hour blocks. I
have looked at all the 3-rd party VCL's on torried delphi pages, in
particular the PIM vcls'. However i'm not looking for a grid layout that
represents a specific week in time, just a general week. I have seen this
sort of thing in the new Vista Parental Control settings for defining when a
computer can be used for the week.
Basically, i have a set of categories and i need to drop them onto a grid
that represents a week. The categories need to be adjusted so that they
span a certain period in time, and can be dropped onto multiple days. Also,
any one period in time could have one or more categories within it.
I have tried to mock up the same functionality using a string grid but i
failed to make it allow me to make multiple selections.
Would it be possible to achieve the same thing with a draw grip? Any ideas
how to facilitate the drag and drop of categories and how to represent this
on the grid?
Many thanks in advance,
Mike C
 

Re:Re: TDrawGrid or week palnner alternative...

Hay JD, thanks for the post - seems pretty spot on. I need to re-read it
and digest - been on the go for 18 hours. Just out of interest, do you have
any working code for this (sounds like you have done it before). if so, any
chance of dropping it to me so i can have an actual look at something. If
possible, my addie is mike [at] softwareassociates [dot] nu
Thanks again,
Mike C
"JD" < XXXX@XXXXX.COM >wrote in message
Quote

 

{smallsort}

Re:Re: TDrawGrid or week palnner alternative...

"Mike Collins" <its@TheBottomOfThePost>wrote:
Quote

[...] been on the go for 18 hours.
What's that like <g>?
Quote
[...] do you have any working code for this
Yes and no.
Quote
(sounds like you have done it before).
Well ... yes and no.
I've done all of things that I spoke of but never for this
purpose.
Quote
[...] any chance of dropping it to me so i can have an
actual look at something.
<Arlo Guthrie>I object to not sharing so I will not!
I'll toss something together to get you started and post it
here for everyone instead!
~ JD
 

Re:Re: TDrawGrid or week palnner alternative...

"JD" < XXXX@XXXXX.COM >wrote:
Quote

I'll toss something together to get you started and post it
here for everyone instead!
Untested:
//-------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//-------------------------------------------------------------
.....
//-------------------------------------------------------------
enum TActivityType
{
faUnspecified = -1,
faFirst,
faSecond,
faThird,
faCount
};
//-------------------------------------------------------------
class TForm1 : public TForm
{
__published:
TStringGrid *StringGrid1;
TImage *Image1;
TImage *Image2;
TImage *Image3;
void __fastcall Image1Click(TObject *Sender);
void __fastcall Image2Click(TObject *Sender);
void __fastcall Image3Click(TObject *Sender);
void __fastcall StringGrid1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y);
void __fastcall StringGrid1DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State);
private:
struct TActivity
{
// fill-in the data fields
int something;
int SomethingElse;
};
TList *FActivityList;
TActivityType FActivity;
public:
__fastcall TForm1(TComponent* Owner);
__fastcall ~TForm1();
};
//-------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//-------------------------------------------------------------
#endif
//-------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//-------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//-------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
FActivity = faUnspecified;
FActivityList = new TList();
StringGrid1->Options = StringGrid1->Options>>goVertLine>>goHorzLine;
StringGrid1->DefaultDrawing = false;
StringGrid1->OnDrawCell = StringGrid1DrawCell;
}
//-------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
for( int x = 0; x < FActivityList->Count; ++x )
{
delete reinterpret_cast<TActivity*>( FActivityList->Items[x] );
}
}
//-------------------------------------------------------------
void __fastcall TForm1::Image1Click(TObject *Sender)
{
FActivity = faFirst;
}
//-------------------------------------------------------------
void __fastcall TForm1::Image2Click(TObject *Sender)
{
FActivity = faSecond;
}
//-------------------------------------------------------------
void __fastcall TForm1::Image3Click(TObject *Sender)
{
FActivity = faThird;
}
//-------------------------------------------------------------
void __fastcall TForm1::StringGrid1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
// trying to emulate the IDE and dropping components
if( Button == mbRight )
{
if( FActivity != faUnspecified )
{
int ACol, ARow;
StringGrid1->MouseToCell( X, Y, ACol, ARow );
if( ACol>= StringGrid1->FixedCols && ARow>= StringGrid1->FixedRows )
{
// was dropped on a valid cell
TActivity *Activity = new TActivity;
FActivityList->Add( Activity );
TActivityForm *pForm = new TActivityForm( this, Activity );
if( pForm->ShowModal() != mrCancel )
{
// OnClose needs to validate or validate here
if( Valid )
{
// assign pForm fields to TActivity. For example:
Activity->Something = 1; // pForm->SomeField
Activity->SomethingElse = 2; // pForm->SomeOtherField
if( StringGrid1->Objects[ACol][ARow] )
{
// an object has already been assigned to this
// cell so descide to insert above or below and
// then call insert on the appropriate row and
// insert it. For example:
TActivity *Activity = reinterpret_cast<TActivity*>( StringGrid1->Objects[ ACol ][ ARow ] );
if( pForm->StartTime>Activity->StartTime )
{
// insert below
}
else
{
// insert above
}
}
else
{
StringGrid1->Objects[ ACol ][ ARow ] = reinterpret_cast<TObject*>( Activity );
}
StringGrid1->Invalidate();
}
}
delete pForm;
}
}
FActivity = faUnspecified;
}
}
//-------------------------------------------------------------
/*
Besides adding logic like a popup menu, that's about all
there is for the GUI. The rest is painting the control so
that it's meaningful to the user (and saving and loading
that has been left to you).
*/
//-------------------------------------------------------------
void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol, int ARow, TRect &Rect, TGridDrawState State)
{
TStringGrid *pGrid = static_cast<TStringGrid*>( Sender );
TCanvas *pCanvas = pGrid->Canvas;
if( State.Contains(gdFixed) )
{
pCanvas->Brush->Color = pGrid->FixedColor;
pCanvas->Font->Color = pGrid->Font->Color;
pCanvas->FillRect( Rect );
}
else
{
pCanvas->Brush->Color = pGrid->Color;
switch( (reinterpret_cast<TAvtivity*>(pGrid->[ACol][ARow]))->ActivityType )
{
case faFirst: pCanvas->Font->Color = clRed; break;
case faSecond: pCanvas->Font->Color = clAqua; break;
case faThird: pCanvas->Font->Color = clYellow; break;
default : pCanvas->Font->Color = pGrid->Font->Color;
}
pCanvas->FillRect( Rect );
}
if( State.Contains(gdFixed) )
{
::DrawText( pCanvas->Handle, pGrid->Cells[ ACol ][ ARow ].c_str(), -1, &Rect, DT_LEFT | DT_VCENTER );
}
else
{
TActivity *Activity = reinterpret_cast<TActivity*>( StringGrid1->Objects[ ACol ][ ARow ] );
// use Activity to paint the cell
}
// optionally draw a focus rect
}
//-------------------------------------------------------------
~ JD
 

Re:Re: TDrawGrid or week palnner alternative...

Hey Mike!
In addition to JD's excellent example, have a look here:
bcbjournal.org/bcbcaq/
Volume 6, Numbers 4 and 6 also contain some extended examples of adding
controls (buttons, drop-down lists, etc) into cells of a string grid.
Look for the "Even more string grids" series.
Cheers,
Mike Collins wrote:
Quote
Hay JD, thanks for the post - seems pretty spot on. I need to re-read it
and digest - been on the go for 18 hours. Just out of interest, do you have
any working code for this (sounds like you have done it before). if so, any
chance of dropping it to me so i can have an actual look at something. If
possible, my addie is mike [at] softwareassociates [dot] nu