campo-sirio/include/sheet.cpp
guy 4759abb8f4 applicat.cpp Aggiunto metodo pre_create per inizializzazioni di basso livello
golem.cpp     Migliorata gestione degli hook agli handler di finestra
msksheet.cpp  Eliminati molti sfarfallamenti duante cambio focus
relapp.cpp    Corretta gestione messaggio ED
sheet.cpp     Corretto posizionamento iniziale su righe disabilitate
xvtility.cpp  Migliorata gestione dell'event hook.


git-svn-id: svn://10.65.10.50/trunk@3328 c028cbd2-c16b-5b4b-a496-9718f37d4682
1996-08-05 09:43:06 +00:00

1239 lines
32 KiB
C++
Executable File

#include <colors.h>
#include <controls.h>
#include <maskfld.h>
#include <relation.h>
#include <sheet.h>
#include <urldefid.h>
#include <utility.h>
#include <xvtility.h>
///////////////////////////////////////////////////////////
// TSheet_control
///////////////////////////////////////////////////////////
class TSheet_control : public TControl
{
enum { FIRST_FIELD = 101, MAX_COL = 128 };
TSheet* _sheet;
long _cur_rec;
// @cmember:(INTERNAL) Tipo di ogni colonna
byte _type[MAX_COL];
// @cmember:(INTERNAL) Indica se e attivata la gestione dei check delle righe
bool _check_enabled;
// @cmember:(INTERNAL) Array di righe attivate
TBit_array _checked;
// @cmember:(INTERNAL) Array di righe disabilitate
TBit_array _disabled;
protected: // TControl
//@cmember Gestisce gli eventi delle celle
virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);
protected:
long items() const { return _sheet->items(); }
TToken_string& row(long n) const { return _sheet->row(n); }
int rec2row(long rec) const;
long row2rec(int row) const;
void make_current(long rec);
public: // TControl
virtual void set_rect(const RCT& r);
public:
long selected() const { return _cur_rec; }
void select(long n);
void set_focus_rec(long rec);
void enable_check(bool on) { _check_enabled = on && _type[0] == 'C'; }
bool check_enabled() const { return _check_enabled; }
void check(long n, bool on);
void toggle(long n);
bool checked(long n) const { return _checked[n]; }
long checked() const { return _checked.ones(); }
bool one_checked() const;
int visible_rows() const;
void enable_row(long r, bool on);
void disable_row(long r);
bool row_enabled(long n) const { return _disabled[n] == FALSE; }
bool one_enabled() const { return _disabled.ones() < _sheet->items(); }
byte& column_type(int c) { CHECKD(c >= 0 && c < MAX_COL, "Bad column ", c); return _type[c]; }
void update(long n = -1);
TSheet_control(WINDOW sheet, short cid,
short x, short y, short dx, short dy,
const char* flags, const char* head);
virtual ~TSheet_control() {}
};
TSheet_control::TSheet_control(
WINDOW parent, // @parm Finestra alla quale appartiene lo spreadsheet
short cid, // @parm Identificatore
short x, // @parm Coordinata x (in caratteri) nel quale posizionare lo spreadsheet
short y, // @parm Coordinata y (in caratteri) nel quale posizionare lo spreadsheet
short dx, // @parm Larghezza (in caratteri) dello spreasheet
short dy, // @parm Lunghezza (in caratteri) dello spreasheet
const char* flags, // @parm Flags di abilitazione
const char* head) // @parm Titolo delle colonne
: _sheet(NULL), _cur_rec(0), _check_enabled(FALSE)
{
const int NUMBER_WIDTH = 7;
short v_width[MAX_COL];
short m_width[MAX_COL];
int fixed_columns = 1; // Number of fixed columns
_sheet = (TSheet*)xvt_vobj_get_data(parent);
// Calcolo larghezza massima tabella
TToken_string header(head);
TToken_string new_header(256);
int i = 0;
int f_width = NUMBER_WIDTH; // Stima larghezza colonne fisse
int max_width = f_width; // Stima larghezza della colonna piu' grande
for (const char* h = header.get(); h; h = header.get(), i++)
{
CHECKD(i < MAX_COL, "Tu meni calumns in scit: ", i);
_type[i] = ' ';
TString testa(h);
const int at = testa.find('@');
int v = testa.len(); // Video width
if (at >= 0)
{
const TString& wi = testa.mid(at+1);
v = atoi(wi);
if (wi.find('F') >= 0)
{
fixed_columns++;
f_width += v+1;
}
if (wi.find('R') >= 0)
_type[i] = 'R'; else
if (wi.find('M') >= 0)
_type[i] = 'M'; else
if (wi.find('C') >= 0)
_type[i] = 'C';
if (i == 0 && v <= 1)
{
_type[i] = 'C';
_check_enabled = TRUE;
fixed_columns++;
f_width += v+1;
}
testa.cut(at);
v = max(at, v);
}
v++;
m_width[i] = v; // v = memory width of column
if (v > 64) v = 64;
v_width[i] = v;
if (v_width[i] > max_width) max_width = v_width[i];
new_header.add(testa);
}
const int _columns = i;
// Calcola rettangolo massimo per lo sheet
XI_RCT rct; coord2rct(parent, x, y, dx, dy, rct);
rct.right -= 2*XI_FU_MULTIPLE; // toglie scroll-bar
// Controlla se ci sono troppe colonne fisse
if ((f_width+max_width)*XI_FU_MULTIPLE > rct.right)
fixed_columns = 1;
XI_OBJ* itf = get_interface(parent);
XI_OBJ_DEF* listdef = xi_add_list_def(NULL, cid,
rct.top, rct.left, rct.bottom-rct.top,
XI_ATR_ENABLED | XI_ATR_VISIBLE,
NORMAL_COLOR, NORMAL_BACK_COLOR, // normal
DISABLED_COLOR, DISABLED_BACK_COLOR, // disabled
FOCUS_COLOR, // active
0);
listdef->app_data = (long)this;
XI_LIST_DEF* l = listdef->v.list;
l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font());
l->sizable_columns = TRUE;
l->movable_columns = TRUE;
l->fixed_columns = fixed_columns;
l->scroll_bar = TRUE;
l->scroll_bar_button = TRUE;
l->white_space_color = MASK_DARK_COLOR;
l->rule_color = MASK_DARK_COLOR;
// Definizione della prima colonna (numero di riga)
const long attr = XI_ATR_VISIBLE | XI_ATR_RJUST | XI_ATR_SELECTABLE;
XI_OBJ_DEF* coldef = xi_add_column_def(listdef, FIRST_FIELD+1000-1, attr, 0,
/* NUMBER_WIDTH*/ 2 * XI_FU_MULTIPLE, NUMBER_WIDTH , "");
coldef->app_data = (long)this;
coldef->v.column->heading_platform = TRUE;
coldef->v.column->column_platform = TRUE;
coldef->v.column->center_heading = TRUE;
for (h = new_header.get(0), i = 0; h; h = new_header.get(), i++)
{
long attr = XI_ATR_VISIBLE | XI_ATR_ENABLED | XI_ATR_AUTOSCROLL | XI_ATR_READONLY;
if (_type[i] == 'C')
attr |= XI_ATR_SELECTABLE;
if (_type[i] == 'R')
attr |= XI_ATR_RJUST;
coldef = xi_add_column_def(listdef, FIRST_FIELD+i+1000, attr, i+1,
v_width[i] * XI_FU_MULTIPLE, m_width[i], (char*)h);
coldef->app_data = (long)this;
coldef->v.column->heading_platform = TRUE;
coldef->v.column->center_heading = TRUE;
if (i == 0 && _type[i] == 'C')
{
coldef->v.column->icon_rid = ICO_CHECK_ON;
if (l->min_heading_height < 20)
l->min_heading_height = 20;
}
}
RCT rd; xi_get_def_rect(listdef, &rd);
if ((rd.right - rd.left) > (rct.right - rct.left))
l->width = rct.right - rct.left;
_obj = xi_create(itf, listdef); // Create the whole thing!
xi_dequeue(); // Flush events in XOL
xi_tree_free(listdef); // Free definitions
CHECKD(_obj, "Can't create spreadsheet ", cid);
update_tab_cid();
// Se la finestra e' troppo grande riducila
RCT cli; xvt_vobj_get_client_rect(parent, &cli);
XI_RCT xc = cli; xi_pu_to_fu(itf, (PNT*)&xc, 2);
if (xc.right > 45 * XI_FU_MULTIPLE) // Deve contenere almeno 4 bottoni
{
xi_get_rect(_obj, &rct);
const int width = rct.right + 2*XI_FU_MULTIPLE;
if (width < cli.right)
{
cli.left += (cli.right - width) / 2;
cli.right = cli.left + width;
xvt_vobj_translate_points(parent, xvt_vobj_get_parent(parent), (PNT*)&cli, 2);
xvt_vobj_move(parent, &cli);
}
}
}
void TSheet_control::set_rect(const RCT& r)
{
const int width = r.right - r.left - 2*XI_FU_MULTIPLE;
const int height = r.bottom - r.top;
xi_set_list_size(_obj, height, width);
}
// Converts a row number in the correspondig record number
int TSheet_control::rec2row(long record) const
{
int rows;
const long* rec = xi_get_list_info(_obj, &rows);
int r = int(record - rec[0]);
if (r < 0 || r >= rows)
r = -1;
return r;
}
// Converts a row number in the correspondig record number
long TSheet_control::row2rec(int row) const
{
int rows;
const long* handle = xi_get_list_info(_obj, &rows);
if (row < 0)
row = 0;
else
{
if (row >= rows)
row = rows-1;
}
const long r = handle[row];
CHECKD(r >= 0 && r < items(), "Sheet line out of range: ", row);
return r;
}
int TSheet_control::visible_rows() const
{
return xi_get_visible_rows(_obj, NULL, NULL);
}
void TSheet_control::update(long n)
{
if (n >= 0)
{
const int riga = rec2row(n);
if (riga >= 0)
{
XI_OBJ row;
XI_MAKE_ROW(&row, _obj, riga);
xi_cell_request(&row);
}
}
else
{
// xi_cell_request(_obj);
int num = 0;
const long* handle = xi_get_list_info(_obj, &num);
bool scroll_first = items() == 0; // || !owner().mask().is_running();
if (!scroll_first)
{
int first = 0, last = 0;
xi_get_visible_rows(_obj, &first, &last);
n = handle[first];
scroll_first = n > items();
}
if (scroll_first)
xi_scroll(_obj, XI_SCROLL_FIRST);
else
xi_scroll_rec(_obj, n, NORMAL_COLOR, XI_ATR_ENABLED, 0);
}
}
void TSheet_control::make_current(long rec)
{
const long old = _cur_rec;
_cur_rec = rec;
XI_OBJ o;
const int oldrow = rec2row(old);
if (oldrow >= 0)
{
XI_MAKE_ROW(&o, _obj, oldrow);
xi_cell_request(&o);
}
const int newrow = rec2row(rec);
if (newrow >= 0 && newrow != oldrow)
{
XI_MAKE_ROW(&o, _obj, newrow);
xi_cell_request(&o);
}
}
void TSheet_control::select(long rec)
{
if (rec >= 0 && rec < items())
{
int rows;
const long* handle = xi_get_list_info(_obj, &rows);
int first = 0, last = 0;
xi_get_visible_rows(_obj, &first, &last);
if (rec < handle[first] || rec > handle[last])
xi_scroll_rec(_obj, rec, NORMAL_COLOR, XI_ATR_ENABLED, 0);
}
make_current(rec);
}
void TSheet_control::set_focus_rec(long rec)
{
if (rec < 0)
rec = selected();
int r = rec2row(rec);
if (r < 0)
{
select(rec);
r = rec2row(rec);
}
const int c = _type[0] == 'C' ? 2 : 1;
XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, r, c);
xi_set_focus(&cell);
}
bool TSheet_control::one_checked() const
{
bool yes = FALSE;
if (check_enabled())
{
const long first = _checked.first_one();
yes = first >= 0;
}
return yes;
}
// @mfunc Permette di attivare/disattivare una riga
void TSheet_control::check(
long n, // @parm Numero della riga da attivare/disattivare
bool on) // @parm Operazione da effettuare sulla riga:
//
// @flag TRUE | Attiva la riga <p n>.esima (default)
// @flag FALSE | Disattiva la riga <p n>.esima
{
if (n < 0)
{
if (on)
{
const long tot = items()-1;
_checked.set(tot); // Forza le dimensioni del bit array
_checked.set(); // Setta tutti i bit
// Elimina i bit in eccesso alla fine dell'array
for (long i = _checked.items()-1; i > tot; i--)
_checked.reset(i);
// Elimina i bit corrispondenti a righe disabilitate
if (_disabled.first_one() >= 0)
{
for (long i = tot; i >= 0; i--)
if (_disabled[i]) _checked.reset(i);
}
}
else
_checked.reset();
// Aggiorna tutta la prima colonna
XI_OBJ* column = xi_get_obj(_obj, FIRST_FIELD+1000);
xi_cell_request(column);
}
else
{
if (!_disabled[n])
_checked.set(n, on);
// Aggiorna la riga
XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, rec2row(n), 1);
xi_cell_request(&cell);
}
}
void TSheet_control::toggle(long n)
{
check(n, !checked(n));
}
// @doc INTERNAL
// @mfunc Abilita/disabilita una riga
void TSheet_control::enable_row(
long n, // @parm Numero della riga da abilitare/diabilitare (default -1)
bool on) // @parm Operazione da svolgere sulla riga
//
// @flag TRUE | Abilita la riga <p n>-esima (default)
// @flag FALSE | Disabilita la riga <p n>-esima
// @comm Se <p n> e' minore di 0 allora vengono abilitate/disabilitate tutte le righe
{
if (n >= 0)
{
_disabled.set(n, !on);
}
else
{
if (on)
_disabled.reset();
else
{
const long tot = items()-1;
_disabled.set(tot); // Forza le dimensioni del bit-array
_disabled.set(); // Disabilita tutte le righe
// Resetta i bit in ecesso alla fine del bit-array
for (long i = _disabled.items()-1; i > tot; i--)
_disabled.reset(i);
}
}
update(n);
}
// Certified 75%
bool TSheet_control::event_handler(XI_OBJ* itf, XI_EVENT *xiev)
{
BOOLEAN& refused = xiev->refused;
switch (xiev->type)
{
case XIE_GET_FIRST:
if (items() > 0L)
{
long n = items() * (long)xiev->v.rec_request.percent / 100L;
if (n < 0L) n = 0L;
xiev->v.rec_request.data_rec = n;
}
else
refused = TRUE;
break;
case XIE_GET_LAST:
xiev->v.rec_request.data_rec = items()-1;
break;
case XIE_GET_PREV:
case XIE_GET_NEXT:
{
const long n = xiev->v.rec_request.spec_rec + (xiev->type == XIE_GET_NEXT ? +1 : -1) ;
if (n < 0 || n >= items())
refused = TRUE;
else
xiev->v.rec_request.data_rec = n;
}
break;
case XIE_CELL_REQUEST:
{
const long rec = xiev->v.cell_request.rec;
const char* src = NULL;
int nm;
XI_OBJ** obj = xi_get_member_list(xiev->v.cell_request.list, &nm);
const int num = xiev->v.cell_request.col_nbr;
const int cid = obj[num]->cid - 1000;
if (cid >= FIRST_FIELD)
{
if (rec < items())
{
const int col = cid - FIRST_FIELD;
switch (_type[col])
{
case 'C': // Set value for "checkable" cell
{
const bool on = checked(rec);
xiev->v.cell_request.icon_rid = on ? ICO_CHECK_ON : ICO_CHECK_OFF;
// if (on) src = "X"; // A volte visualizza la X!
}
break;
case 'M': // Set value for "roman" cell
src = itor(atoi(row(rec).get(col)));
break;
default: // Set value for "normal" cell
src = row(rec).get(col);
break;
}
if (_disabled[rec])
{
xiev->v.cell_request.color = DISABLED_COLOR;
xiev->v.cell_request.back_color = DISABLED_BACK_COLOR;
}
else
if (rec == _cur_rec)
{
xiev->v.cell_request.color = FOCUS_COLOR;
xiev->v.cell_request.back_color = FOCUS_BACK_COLOR;
}
}
}
else
{
xiev->v.cell_request.color = NORMAL_COLOR;
// src = format("%ld", rec+1);
src = "";
}
char* dst = xiev->v.cell_request.s;
if (src && *src)
{
const int len = xiev->v.cell_request.len;
strncpy(dst, src, len);
dst[len-1] = '\0';
}
else
*dst = '\0';
}
break;
case XIE_DBL_CELL:
{
const long rec = row2rec(xiev->v.xi_obj->v.cell.row);
if (!_disabled[rec])
{
make_current(rec);
_sheet->stop_run(K_ENTER);
}
else
refused = TRUE;
}
break;
case XIE_ON_ROW:
{
const long rec = row2rec(xiev->v.xi_obj->v.row);
if (_disabled[rec])
{
refused = TRUE;
// Cerca la prossima riga abilitata e valida
const int dir = rec > selected() ? +1: -1;
const long max = items();
for (long r = rec+dir; r >= 0 && r < max; r += dir) if (!_disabled[r])
{
_sheet->post_select(r);
break;
}
}
else
if (_sheet->_select_row < 0)
make_current(rec);
}
break;
case XIE_GET_PERCENT:
{
const long rec = xiev->v.get_percent.record;
long n = items(); if (n <= 0) n = 1;
xiev->v.get_percent.percent = int(rec * 100L / n);
}
break;
case XIE_SELECT:
if (xiev->v.xi_obj->type == XIT_ROW)
{
int num;
XI_OBJ** column = xi_get_member_list(_obj, &num);
const int col = xiev->v.select.column;
const int row = xiev->v.select.xi_obj->v.row;
const long rec = row2rec(row);
const short cid = column[col]->cid - 1000;
if (cid >= FIRST_FIELD)
{
if (check_enabled())
toggle(rec);
}
else
{
if (_cur_rec == rec)
_sheet->on_key(K_CTRL+'G');
}
const int c = _type[0] == 'C' ? 2 : 1;
XI_OBJ cell; XI_MAKE_CELL(&cell, _obj, row, c);
xi_set_focus(&cell);
make_current(rec);
}
refused = TRUE;
break;
case XIE_BUTTON:
if (xiev->v.xi_obj->type == XIT_LIST)
_sheet->on_key(K_CTRL+'N');
break;
case XIE_XVT_EVENT:
if (xiev->v.xvte.type == E_CHAR)
{
const KEY k = e_char_to_key(&xiev->v.xvte);
long rec = -1;
switch (k)
{
case K_SPACE:
check(selected(), !checked(selected()));
break;
case K_ENTER:
if (_disabled[_cur_rec])
break;
case K_ESC:
_sheet->stop_run(k);
break;
case K_LHOME:
rec = 0;
break;
case K_PREV:
rec = _cur_rec - visible_rows();
if (rec < 0) rec = 0;
break;
case K_NEXT:
rec = _cur_rec + visible_rows();
if (rec >= items())
rec = items()-1;
break;
case K_LEND:
rec = items()-1;
break;
default:
break;
}
if (rec >= 0)
{
_sheet->post_select(rec);
refused = TRUE;
}
}
break;
default:
break;
}
return !refused;
}
///////////////////////////////////////////////////////////
// TQuery_field
///////////////////////////////////////////////////////////
class TQuery_field : public TOperable_field
{
protected:
virtual void create(WINDOW parent);
public:
TSheet_control* sheet() const { return (TSheet_control*)_ctl; }
TQuery_field(TMask* m) : TOperable_field(m) { }
virtual ~TQuery_field() { }
};
void TQuery_field::create(WINDOW parent)
{
_ctl = new TSheet_control(parent, dlg(),
_ctl_data._x, _ctl_data._y,
_ctl_data._width, _ctl_data._size,
_ctl_data._flags, _ctl_data._prompt);
}
///////////////////////////////////////////////////////////
// TSheet
///////////////////////////////////////////////////////////
TSheet::TSheet(short x, short y, short dx, short dy,
const char* title, const char* head,
byte buttons, short sht_y)
: TMask(title, sht_y == 0 ? 1 : 2, dx, dy, x, y),
_parked(-1), _sheet(NULL), _select_row(-1)
{
TQuery_field* qf = new TQuery_field(this);
qf->construct(30883, head, 1, sht_y, -3, win(), "", -1);
fields_array().add(qf);
_sheet = qf->sheet();
if (!(buttons & 0x10)) add_button(DLG_SELECT, "Selezione", K_ENTER);
if (check_enabled())
{
add_button(DLG_USER, "Tutti", 0);
set_handler(DLG_USER, tutti_handler);
}
if (buttons & 0x1) add_button(DLG_LINK, "~Gestione", K_CTRL+'G');
if (buttons & 0x2) add_button(DLG_NEWREC, "~Nuovo", K_INS, BMP_NEWREC, BMP_NEWRECDN);
if (buttons & 0x4) add_button(DLG_DELREC, "Elimina", K_DEL, BMP_DELREC, BMP_DELRECDN);
if (buttons & 0x8) add_button(DLG_QUIT, "Fine", K_ESC);
else add_button(DLG_CANCEL, "Annulla", K_ESC);
}
TSheet::~TSheet()
{
delete _sheet;
}
TSheet_control& TSheet::sheet()
{ return *_sheet; }
// @doc INTERNAL
// @mfunc Aggiunge un bottone nella finestra
void TSheet::add_button(
short id, // @parm Identificatore del bottone da aggiungere
const char* caption, // @parm Testo del bottone da aggiungere
KEY key, // @parm Combinazione di tasti corrispondente
short bmp_up, // @parm Bitmap normale
short bmp_dn) // @parm Bitmap premuta
{
TButton_field& butt = TMask::add_button(id, 0, caption, 0, -1, 11, 2,
"", bmp_up, bmp_dn);
butt.set_hot_key(key);
}
void TSheet::repos_buttons() const
{
if (_sheet == NULL)
return; // Sono ancora in fase di creazione: aspetta!
RCT br;
int buttons = 0;
for (int f = fields()-1; f >= 0; f--)
{
TMask_field& c = fld(f);
if (c.is_kind_of(CLASS_BUTTON_FIELD))
{
if (buttons == 0)
c.get_rect(br);
buttons++;
}
}
RCT wr; xvt_vobj_get_client_rect(win(), &wr);
const short width = br.right - br.left;
const short height = br.bottom - br.top;
int space = (wr.right - buttons * width) / (buttons+1);
if (space < 0) space = 0;
int x = space;
const int y = wr.bottom - height - XI_FU_MULTIPLE;
for (f = 0; buttons > 0; f++)
{
TMask_field& c = fld(f);
if (c.is_kind_of(CLASS_BUTTON_FIELD))
{
buttons--;
const PNT p = { y, x };
xvt_rect_set_pos(&br, p);
c.set_rect(br);
x += space+width;
}
}
}
void TSheet::start_run()
{
const bool on = items() > 0 && _sheet->one_enabled();
// Abilita selezione se c'e' almeno un elemento
int pos = id2pos(DLG_SELECT);
if (pos >= 0)
fld(pos).enable(on);
pos = id2pos(DLG_LINK);
if (pos >= 0)
fld(pos).enable(on);
_parked = -1;
repos_buttons();
_sheet->update();
if (on)
{
long i = selected();
if (i < 0 || i >= items())
i = 0;
if (row_disabled(i))
for (i = 0; row_disabled(i); i++);
post_select(i);
}
}
long TSheet::selected() const
{ return _sheet->selected(); }
bool TSheet::check_enabled() const
{ return _sheet->check_enabled(); }
void TSheet::enable_check(bool on)
{ _sheet->enable_check(on); }
void TSheet::check(long n, bool on)
{ _sheet->check(n, on); }
bool TSheet::checked(long n) const
{ return _sheet->checked(n); }
long TSheet::checked() const
{ return _sheet->checked(); }
bool TSheet::one_checked() const
{ return _sheet->one_checked(); }
void TSheet::enable_row(long r, bool on)
{ _sheet->enable_row(r, on); }
bool TSheet::row_enabled(long r) const
{ return _sheet->row_enabled(r); }
bool TSheet::on_key(KEY key)
{
switch(key)
{
case K_ESC:
stop_run(key);
break;
case K_DEL:
if (items() && id2pos(DLG_DELREC) >= 0)
stop_run(key);
break;
case K_CTRL+'N':
if (id2pos(DLG_NEWREC) >= 0)
stop_run(K_INS);
break;
case K_CTRL+'G':
if (id2pos(DLG_LINK) >= 0)
stop_run(key);
break;
default:
break;
}
if (check_enabled() && items() > 0)
{
switch(key)
{
// case K_SPACE:
// check(selected(), !checked(selected()));
// break;
case K_F7:
uncheck(-1);
break;
case K_F8:
check(-1);
break;
default:
break;
}
}
return TRUE;
}
// @doc INTERNAL
// @mfunc Seleziona una riga facendola diventare corrente
void TSheet::select(
long n) // @parm Riga da selezionare
{
_sheet->select(n);
}
void TSheet::post_select(long rec)
{
_select_row = rec;
}
void TSheet::on_idle()
{
if (_select_row >= 0)
{
const short focus_id = get_focus_id(win());
_sheet->select(_select_row);
if (focus_id == _sheet->id())
_sheet->set_focus_rec(-1);
_select_row = -1;
}
}
// @doc INTERNAL
// @mfunc Ritorna il contenuto di una riga
//
// @rdesc Ritorna la <c TToken_string> con tutti gli elemnti della riga
TToken_string& TSheet::row(
long n) // @parm Riga di cui ritorna il contenuto (default -1)
// @comm Se viene passato un numero di riga minore di 1 viene ritornato il contenuto della riga
// selezionata.
{
if (n < 0) n = selected();
if (n != _parked)
get_row(_parked = n, _park);
return _park;
}
bool TSheet::tutti_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TSheet& s = (TSheet&)f.mask();
if (s.check_enabled())
s.check(-1, !s.one_checked());
}
return TRUE;
}
///////////////////////////////////////////////////////////
// TArray_sheet
///////////////////////////////////////////////////////////
TArray_sheet::TArray_sheet(short x, short y, short dx, short dy,
const char* caption, const char* head, byte buttons)
: TSheet(x, y, dx, dy, caption, head, buttons)
{
}
// Certified 90%
bool TArray_sheet::destroy(int i)
{
uncheck(-1);
enable(-1);
return _data.destroy(i, TRUE);
}
// @doc EXTERNAL
// @mfunc Aggiunge un elemento allo sheet
//
// @rdesc Ritorna il numero di elemnti presenti nello sheet
long TArray_sheet::add(
const TToken_string& s) // @parm Oggetto da aggiungere
// @parm const TToken_string | *s | Oggetto da aggiungere passato per indirizzo
// @syntax add(const TToken_string& s)
// @syntax add(const TToken_string* s)
{
const long n = _data.add(s);
return n;
}
long TArray_sheet::add(TToken_string* s)
{
const long n = _data.add(s);
return n;
}
long TArray_sheet::insert(const TToken_string& s, long n)
{
_data.insert(s, (int)n);
return n;
}
///////////////////////////////////////////////////////////
// TCursor_sheet
///////////////////////////////////////////////////////////
TCursor_sheet::TCursor_sheet(TCursor* cursor, const char* fields,
const char* title, const char* head,
byte buttons, short sht_y)
: TSheet(sht_y ? 3 : 0, sht_y ? 3 : 0, sht_y ? -3 : 0, sht_y ? -3 : 0,
title, head, buttons, sht_y),
_cursor(cursor), _records(cursor->items())
{
TToken_string fldlst(fields);
int campo = 0;
for (const char* t = fldlst.get(0); t; t = fldlst.get(), campo++)
{
if (*t > ' ' && *t != '"')
{
const TFieldref fr(t, 0);
TRecfield* rf = new TRecfield(_cursor->curr(fr.file()),
fr.name(), fr.from(), fr.to() - 1);
_fields.add(rf, campo);
const TFieldtypes tipo = rf->type();
if (tipo == _intfld || tipo == _longfld || tipo == _realfld)
{
byte& c = sheet().column_type(campo);
if (c == '\0') c = 'R'; // Allinea a destra tutti i campi numerici
}
}
}
}
HIDDEN bool _can_post = FALSE;
KEY TCursor_sheet::run()
{
_records = _cursor->items();
_cursor->freeze(TRUE);
select(_cursor->pos());
// post_select(_cursor->pos());
_can_post = TRUE;
const KEY k = TSheet::run();
_cursor->freeze(FALSE);
return k;
}
void TCursor_sheet::get_row(long row, TToken_string& l)
{
*_cursor = (TRecnotype)row;
l.cut(0);
const int last = _fields.last();
for (int i = 0; i <= last; i++)
{
const TRecfield* rf = (TRecfield*)_fields.objptr(i);
const char* s = rf ? (const char*)*rf : "";
l.add(s);
}
}
///////////////////////////////////////////////////////////
// TBrowse_sheet
///////////////////////////////////////////////////////////
HIDDEN TBrowse_sheet* _cur_browse = NULL;
bool TBrowse_sheet::browse_field_handler(TMask_field& f, KEY k)
{
long rec = -1;
if (k == K_SPACE)
{
TEdit_field& e = _cur_browse->field(); // Campo padre dello sheet
TMask& m = e.mask(); // Maschera che contiene lo sheet
TMask_field& c = m.field(f.dlg()); // Campo corrispondente sulla maschera
// Ricopia su campo maschera
if (f.is_edit())
{
TEdit_field& ef = (TEdit_field&)f;
const TString& wd = ef.get_window_data();
c.set(wd);
}
else
c.set(f.get());
TBrowse* b = e.browse();
b->do_input(FALSE);
rec = b->cursor()->read(_isgteq);
} else
if (k == K_F2)
rec = 0;
if (rec >= 0 && rec != _cur_browse->selected())
{
_cur_browse->select(rec); // Non mettere post_select
_can_post = TRUE;
RCT r; f.get_rect(r);
xvt_dwin_invalidate_rect(f.parent(), &r);
}
return TRUE;
}
bool TBrowse_sheet::last_browse_field_handler(TMask_field& f, KEY k)
{
const bool ok = browse_field_handler(f, k);
if (ok)
{
if (k == K_TAB && _can_post)
{
_cur_browse->post_select(_cur_browse->selected());
_can_post = FALSE;
}
else
{
if (k == K_CTRL+K_TAB)
{
RCT r; f.get_rect(r);
xvt_dwin_invalidate_rect(f.parent(), &r);
}
}
}
return ok;
}
TBrowse_sheet::TBrowse_sheet(TCursor* cursor, const char* fields,
const char* title, const char* head, byte buttons,
TEdit_field* f, TToken_string& sibling)
: TCursor_sheet(cursor, fields, title, head, buttons, f->browse()->input_fields()),
_field(f), _sel(0)
{
TToken_string ca; // Tag buttons
int n = 0;
for (const char* s = sibling.get(0); s && *s; s = sibling.get(), n++)
{
const short id = f->atodlg(s);
const char* pr = sibling.get();
if (id == f->dlg())
{
_sel = n;
}
ca.add(pr);
}
if (n > 0)
add_tag_button(0, ca, _sel);
TToken_string tids = head;
TToken_string tfns = fields;
TToken_string ids = f->browse()->get_input_fields();
TToken_string fns = f->browse()->get_input_field_names();
TEditable_field* e = NULL;
short y = 0;
for (const char* i = ids.get(0); i; i = ids.get())
{
if (*i != '"' && strchr(i, '@') == NULL)
{
const TMask_field& c = f->mask().field(f->atodlg(i));
if (c.is_editable() && c.active())
{
int pos = ids.get_pos(c.dlg());
CHECK(pos >= 0, "Invalid input field");
TString80 p = fns.get(pos);
pos = tfns.get_pos(p);
if (pos >= 0)
{
p = tids.get(pos);
pos = p.find('@');
if (pos >= 0)
p.cut(pos);
}
else
p.cut(0);
if (p.empty())
{
p = c.prompt();
// Toglie spazi e simboli iniziali dal prompt
for (int a = 0; p[a] && !isalnum(p[a]); a++);
p.ltrim(a);
}
p.left_just(16);
TString16 flags;
if (c.roman()) flags << 'M';
if (c.right_justified()) flags << 'R';
if (c.uppercase()) flags << 'U';
if (c.zerofilled()) flags << 'Z';
switch (c.class_id())
{
case CLASS_EDIT_FIELD:
e = &add_string(c.dlg(), 0, p, 1, y++, c.size(), flags, c.size() > 50 ? 50 : c.size() );
break;
case CLASS_REAL_FIELD:
e = &add_number(c.dlg(), 0, p, 1, y++, c.size(), flags);
break;
case CLASS_DATE_FIELD:
e = &add_date (c.dlg(), 0, p, 1, y++, flags);
break;
default:
e = NULL;
break;
}
if (e)
{
e->set_handler(browse_field_handler);
e->set(c.get());
if (e->dlg() == f->dlg())
first_focus(e->dlg());
}
}
}
}
if (e != NULL)
e->set_handler(last_browse_field_handler);
}
bool TBrowse_sheet::on_key(KEY k)
{
if (k >= K_CTRL+K_F1 && k < K_CTRL+K_F10)
{
const int what = k - K_CTRL - K_F1;
if (what >= 0 && what != _sel)
TWindow::stop_run(k);
return TRUE;
}
return TSheet::on_key(k);
}
KEY TBrowse_sheet::run()
{
_cur_browse = this;
const KEY key = TCursor_sheet::run();
_cur_browse = NULL;
return key;
}