campo-sirio/include/sheet.cpp
alex 04223ee489 Patch level : 10.0 98
Files correlati     : cg2.exe tutti i programmi
Ricompilazione Demo : [ ]
Commento           :

Bug 0000837

Sto cambiando data ad un gruppo di registrazioni fatture di vendita manuale, per far
rigenerare le scadenze metto reg. di pura iva prima si e poi no, non mi ricrea le righe
di contabilità quindi mi appresto ad inserirle io, ricerco quindi il cliente ma la barra di
ricerca nasconde l'imbuto di ricerca, ed il campo della ragione sociale viene accorpato
al campo alla destra.


git-svn-id: svn://10.65.10.50/trunk@16972 c028cbd2-c16b-5b4b-a496-9718f37d4682
2008-07-30 07:26:07 +00:00

1966 lines
51 KiB
C++
Executable File

#define XI_INTERNAL
#include <xinclude.h>
#include <statbar.h>
#include <applicat.h>
#include <colors.h>
#include <config.h>
#include <controls.h>
#include <relation.h>
#include <sheet.h>
#include <toolfld.h>
#include <urldefid.h>
#include <utility.h>
#include <xvtility.h>
///////////////////////////////////////////////////////////
// TSheet_control
///////////////////////////////////////////////////////////
class TSheet_control : public TControl
{
enum { FIRST_FIELD = 101, MAX_COL = 256 };
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;
// @cmember:(INTERNAL) Array delle largezze standard
int _default_width[MAX_COL];
byte _save_columns_order;
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);
XI_OBJ* find_column(int col) const;
XI_OBJ* find_column(const char* head) const;
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);
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) const { CHECKD(c >= 0 && c < MAX_COL, "Bad column ", c); return _type[c]; }
void align_column(int c, bool right);
void set_columns_order(TToken_string* order);
void save_columns_order(const TEdit_field& f) const;
void load_columns_order(const TEdit_field& f);
void update(long n = -1);
bool head(int c, TString& str) const;
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),
_save_columns_order(FALSE)
{
const int NUMBER_WIDTH = 7;
short v_width[MAX_COL];
short m_width[MAX_COL];
int fixed_columns = 1; // Number of fixed columns
int lines_in_cell = 1;
_sheet = (TSheet*)xvt_vobj_get_data(parent);
// Calcolo larghezza massima tabella
TToken_string header(head);
TToken_string new_header(header.size());
int f_width = NUMBER_WIDTH; // Stima larghezza colonne fisse
int max_width = f_width; // Stima larghezza della colonna piu' grande
int lines_in_header = 1;
const char * h;
int i = 0;
for (h = header.get(); h && i < MAX_COL; h = header.get(), i++)
{
_type[i] = ' ';
TString testa(h);
char* t = testa.get_buffer();
for (int c = 0; t[c]; c++)
{
if (t[c] == '\\' && (t[c+1] == 'n' || t[c+1] == 'r'))
{
t[c] = '\n';
strcpy(t+c+1, t+c+2);
}
if (t[c] == '\n')
lines_in_header = 2;
}
const int at = testa.rfind('@');
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('V') >= 0)
_type[i] = 'V'; else
if (wi.find('P') >= 0)
_type[i] = 'P'; 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);
if (v == 0) v = at;
}
if (v > 64)
{
lines_in_cell = (v-1) / 64 + 1;
v = 64;
}
m_width[i] = v*lines_in_cell + 1;
v_width[i] = v+1;
if (v > max_width)
max_width = v;
new_header.add(testa);
}
// Calcola rettangolo massimo per lo sheet
// RCT rct; coord2rct(parent, x, y, dx, dy, rct);
// rct.right -= 2*XI_FU_MULTIPLE; // toglie scroll-bar
RCT rct; coord2rct(parent, x, y, -2, -2, rct);
// 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 | XI_ATR_NAVIGATE,
NORMAL_COLOR, NORMAL_BACK_COLOR, // normal
NORMAL_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(xi_get_system_font()) * lines_in_header;
// l->min_heading_height = xi_button_calc_height_font_id(xvt_default_font()) * lines_in_header;
l->max_lines_in_cell = lines_in_cell;
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;
#ifdef LINUX
l->scroll_on_thumb_track = TRUE;
#endif
// 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,
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 && i < MAX_COL; 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' || _type[i] == 'V' || _type[i] == 'P') // Right, Currency, Price
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 (m_width[i] > 64)
coldef->v.column->wrap_text = TRUE;
if (i == 0 && _type[i] == 'C')
{
coldef->v.column->icon_rid = ICO_CHECK_ON;
coldef->v.column->icon_mode = XIM_ICON_HAS_PRIORITY;
if (l->min_heading_height < 20)
l->min_heading_height = 20;
}
}
RCT rd; xi_get_def_rect(listdef, (XinRect *) &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_get_rect(_obj, (XinRect*)&rct);
const int extra = (cli.right - (rct.right-rct.left+2*XI_FU_MULTIPLE)) / 2;
if (extra > XI_FU_MULTIPLE)
{
WINDOW main_win = _sheet->win();
xvt_vobj_get_outer_rect(main_win, &cli);
cli.left += extra;
cli.right -= extra;
xvt_vobj_move(main_win, &cli);
xvt_vobj_get_client_rect(parent, &cli);
}
int num;
XI_OBJ** column = xi_get_member_list(_obj, &num);
for (i = 0; i < num; i++)
{
RCT rct; xi_get_rect(column[i], (XinRect *) &rct);
_default_width[i] = rct.right - rct.left;
}
}
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);
}
XI_OBJ* TSheet_control::find_column(
int col) const // @parm Indice o identificatore colonna
{
CHECKD(col >= 0, "Bad column ", col);
if (col < FIRST_FIELD) // Se e' un indice trasformalo in identificatore
col += FIRST_FIELD + 1000;
int num;
XI_OBJ** columns = xi_get_member_list(_obj, &num);
int c;
for (c = num-1; c >= 0; c--)
{
if (columns[c]->cid == col)
break;
}
return c >= 0 ? columns[c] : NULL;
}
XI_OBJ* TSheet_control::find_column(
const char* head) const // @parm testata colonna
{
int num;
XI_OBJ** column = xi_get_member_list(_obj, &num);
int c;
for (c = num-1; c >= 0; c--)
{
char str[80];
xi_get_text(column[c], str, sizeof(str));
if (strcmp(str, head) == 0)
break;
}
return c >= 0 ? column[c] : NULL;
}
bool TSheet_control::head(int c, TString& str) const
{
XI_OBJ* col = find_column(c);
if (col != NULL)
xi_get_text(col, str.get_buffer(80), 80);
else
str.cut(0);
return col != NULL;
}
void TSheet_control::enable_check(bool on)
{
_check_enabled = on && _type[0] == 'C';
if (_type[0] == 'C')
{
XI_OBJ* column = find_column(1101);
CHECK(column, "Can't find checkable column");
dword attr = xi_get_attrib(column);
if (_check_enabled) attr |= XI_ATR_ENABLED;
else attr &= ~XI_ATR_ENABLED;
xi_set_attrib(column, attr); // Set new attributes
}
}
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;
if (tot >= 0)
{
_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
if (_sheet->is_running())
{
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);
}
void TSheet_control::save_columns_order(const TEdit_field& field) const
{
if (_save_columns_order)
{
TString parag;
if (_sheet->get_ini_paragraph(field, parag))
{
TConfig config(CONFIG_USER, parag); // Apre il file di configurazione
TToken_string order(127); // Nuovo ordine delle colonne
if (_save_columns_order == TRUE) // Se vale 3 devo solo resettare
{
int num;
XI_OBJ** column = xi_get_member_list(_obj, &num);
for (int i = 0; i < num; i++) // Scorre tutte le colonne
{
TString h;
char head[80];
xi_get_text(column[i], head, sizeof(head));
for (const char * s = head; *s; s++)
{
if (*s == '\n')
h << "\\n";
else
h << *s;
}
order.add(h);
RCT rct; xi_get_rect(column[i], (XinRect *) &rct);
order << ',' << rct.right - rct.left;
}
config.set("Browse", order, NULL, TRUE, field.dlg());
}
else
config.remove("Browse", field.dlg());
}
}
}
void TSheet_control::load_columns_order(const TEdit_field& field)
{
TFilename parag;
if (_sheet->get_ini_paragraph(field, parag))
{
TConfig config(CONFIG_USER, parag);
const int index = field.dlg();
TToken_string order(esc(config.get("Browse", NULL, index)));
if (order.empty_items())
config.remove("Browse", index);
else
set_columns_order(&order);
}
_save_columns_order = FALSE;
}
void TSheet_control::align_column(int c, bool right)
{
XI_OBJ* column = find_column(c);
CHECKD(column, "Can't find numeric column ", c);
dword attr = xi_get_attrib(column);
if (right)
attr |= XI_ATR_RJUST;
else
attr &= ~XI_ATR_RJUST;
xi_set_attrib(column, attr);
_type[c] = right ? 'R' : ' ';
}
void TSheet_control::set_columns_order(TToken_string* order)
{
XI_OBJ* itf = get_interface();
XI_OBJ* focus = xi_get_focus(itf);
xi_set_focus(itf);
int num_cols;
xi_get_member_list(_obj, &num_cols); //verificare
// Costante da sottrarre nella xi_column_set_pixel_width altrimenti la somma due volte!
const int offset = 2 * (int)xi_get_pref(XI_PREF_COLUMN_OFFSET);
if (order == NULL)
{
for (int index = 0; index < num_cols; index++)
{
const short cid = FIRST_FIELD + 1000 + index - 1;
XI_OBJ* col = find_column(cid);
if (col)
{
xi_move_column(col, index);
RCT rct; xi_get_rect(col, (XinRect*)&rct);
if (_default_width[index] != rct.right - rct.left)
xi_column_set_pixel_width(col, _default_width[index]-offset);
}
}
_save_columns_order = 0x3;
}
else
{
TString head(23);
TToken_string col(8, ',');
int pos = 0;
for (col = order->get(0); !col.blank(); col = order->get(), pos++)
{
head = col.get(0);
const int width = col.get_int();
XI_OBJ* column = find_column(head);
if (column) // Controlla che esista ancora
{
if (pos > 0 && pos < num_cols)
xi_move_column(column, pos); // Sposta la colonna se possibile
if (width > XI_FU_MULTIPLE) // Se ha una larghezza valida
xi_column_set_pixel_width(column, width - offset);
}
}
}
if (focus)
xi_set_focus(focus);
}
HIDDEN long _rec_to_select = -1;
// 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 >= 0 && 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;
}
break;
case 'M': // Set value for "roman" cell
src = itor(atoi(row(rec).get(col)));
break;
case 'V': // Set value for "value" cell
{
const real r = row(rec).get(col);
TCurrency c(r);
src = c.string(TRUE);
}
break;
case 'P': // Set value for "price" cell
{
const real r = row(rec).get(col);
TPrice c(r);
src = c.string(TRUE);
}
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
_sheet->get_cell_colors(rec, col, xiev->v.cell_request.color, xiev->v.cell_request.back_color);
}
else
refused = TRUE;
}
else
{
xiev->v.cell_request.color = NORMAL_COLOR;
// src = format("%ld", rec+1); // Niente piu' numeri di riga!
}
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_LIST:
_sheet->notify_focus_field(id());
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);
else
_rec_to_select = 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)
{
const int row = xiev->v.select.xi_obj->v.row;
const long rec = row2rec(row);
if (row_enabled(rec))
{
int num;
XI_OBJ** column = xi_get_member_list(_obj, &num);
const int col = xiev->v.select.column;
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_COL_MOVE:
if (xiev->v.column.in_fixed ||
xiev->v.column.col_nbr < xi_get_fixed_columns(xiev->v.column.list))
refused = TRUE;
else
_save_columns_order = TRUE;
break;
case XIE_COL_SIZE:
{
if (_obj->v.list->hsb_win)
_save_columns_order = TRUE;
else
refused = TRUE; // Non permetto il resize in assenza di scroll bar orizzontale
}
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:
if (_check_enabled)
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, (int)_ctl_data._size,
_ctl_data._flags, _ctl_data._prompt);
}
///////////////////////////////////////////////////////////
// TSheet
///////////////////////////////////////////////////////////
#define DLG_QUERY 25883
TSheet::TSheet(short x, short y, short dx, short dy,
const char* title, const char* head,
byte buttons, short sht_y, WINDOW parent)
: TMask(title, 1, dx, dy, x, y, parent),
_sheet(NULL), _select_row(-1), _parked(-1)
{
#ifdef OLD_FASHIONED_BROWSE
if (sht_y > 0) // Crea notebook se TBrowse_sheet
{
create_book(false); // Crea notebook e poi ...
create_page(title, 0); // ... la sua prima pagina
}
#endif
create_bar(1); // Crea toolbar in alto
TQuery_field* qf = new TQuery_field(this);
qf->construct(DLG_QUERY, head, 1, sht_y, 0, page_win(0), "", 0);
fields_array().add(qf);
_sheet = qf->sheet();
if (!(buttons & 0x10))
add_button(DLG_SELECT, TR("~Selezione"), K_ENTER, BMP_OK);
if (check_enabled())
{
add_button(DLG_USER, TR("~Tutti"), 0, BMP_SELECT);
set_handler(DLG_USER, tutti_handler);
}
if (buttons & 0x01) add_button(DLG_LINK, TR("Colle~ga"), K_CTRL+'G', BMP_LINK);
if (buttons & 0x02) add_button(DLG_NEWREC, TR("~Nuovo"), K_INS, BMP_NEWREC);
if (buttons & 0x04) add_button(DLG_DELREC, "~Elimina", K_DEL, BMP_DELREC);
add_button(DLG_SAVEREC, TR("~Esporta"), 0, TOOL_EXPORT);
set_handler(DLG_SAVEREC, export_handler);
if (buttons & 0x08) add_button(DLG_QUIT, "Fine", K_ESC, BMP_QUIT);
else add_button(DLG_CANCEL, "Annulla", K_ESC, BMP_CANCEL);
xvt_toolbar_realize(toolbar()); // Necessario per calcolare dimensioni corrette dello sheet
}
TSheet::~TSheet()
{
// delete _sheet; // Guy bestia: Already deleted by TMask!
}
TSheet_control& TSheet::sheet()
{ return *_sheet; }
// Costruisce l'identificatore del paragrafo contenente la disposizione
// delle colonne del campo f
bool TSheet::get_ini_paragraph(const TEdit_field& f, TString& name) const
{
const TMask& m = f.mask();
name = m.source_file().name();
if (name.blank()) // Maschera dinamica
name = main_app().name();
else
name = name.before("."); // Nome della maschera senza estensione
const int index = m.number();
CHECKD(index >= 0 && index <= 8, "Bad mask index:", index);
if (index > 0) // Aggiunge l'eventuale numero di sotto-maschera
name << '(' << index << ')';
return true;
}
// @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
{
if (bmp_up <= 0)
{
if (toolwin() == NULL_WIN)
create_bar(-2); // Forza la creazione della bottom bar
TButton_field& butt = TMask::add_button(id, MAX_PAGES, caption, 0, -1, 11, 2);
butt.set_exit_key(key);
}
else
{
TButton_tool& butt = add_button_tool(id, caption, bmp_up);
butt.set_exit_key(key);
}
}
bool TSheet::get_cell_colors(int row, int col, COLOR& fore, COLOR& back) const
{
fore = back = 0; // Default colors
if (EASY_RIDER && (row & 1))
back = EASY_RIDER_COLOR;
return false; // Not assigned
}
void TSheet::repos_buttons() const
{
if (_sheet == NULL)
return; // Sono ancora in fase di creazione: aspetta!
WINDOW btnwin = toolwin(); // was win()
RCT br, wr;
int buttons = 0;
FOR_EACH_MASK_FIELD((*this), f, c)
{
if (c->parent() == btnwin && c->is_kind_of(CLASS_BUTTON_FIELD))
{
if (buttons == 0)
c->get_rect(br);
buttons++;
}
}
if (buttons > 0)
{
xvt_vobj_get_client_rect(btnwin, &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) / 2;
FOR_EACH_MASK_FIELD((*this), f, c)
{
if (c->parent() == btnwin && 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;
}
}
}
// Aggiusta anche lo spreadsheet se necessario
TMask_field& s = field(DLG_QUERY);
xvt_vobj_get_client_rect(s.parent(), &wr);
s.get_rect(br);
if (br.bottom > wr.bottom || (wr.bottom-br.bottom) > 48)
{
br.bottom = wr.bottom - br.left; // Lascio uno spazio in fondo pari al bordo sinistro
s.set_rect(br);
}
}
void TSheet::force_update(int r)
{
_sheet->update(r);
}
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);
reset_parked();
repos_buttons();
force_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_CTRL+'E':
case K_DEL:
if (items() && id2pos(DLG_DELREC) >= 0)
stop_run(K_DEL);
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;
case K_CTRL+'S':
if (id2pos(DLG_SELECT) >= 0)
stop_run(K_ENTER);
break;
default:
key -= K_CTRL;
if (key >= 'A' && key <= 'Z')
{
for (int i = fields()-1; i >= 0; i--)
{
TMask_field& f = fld(i);
if (f.active() && f.is_kind_of(CLASS_BUTTON_FIELD))
{
TButton_field& b = (TButton_field&)f;
if (b.virtual_key() == key)
{
f.on_key(K_SPACE);
if (b.exit_key() > 0)
stop_run(b.exit_key());
return TRUE;
}
}
}
}
break;
}
if (check_enabled() && items() > 0)
{
switch(key)
{
case K_CTRL+'E':
export_handler(field(DLG_SAVEREC), K_SPACE);
break;
case K_CTRL+'T':
tutti_handler(field(DLG_USER), K_SPACE);
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 = low_get_focus_id(win());
_sheet->select(_select_row);
if (focus_id == _sheet->id())
_sheet->set_focus_rec(-1);
_select_row = -1;
}
TMask::on_idle();
}
// @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;
}
bool TSheet::export_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TSheet& s = (TSheet&)f.mask();
FILE_SPEC fs;
TFilename name;
s.get_caption(name); name.ext("xls");
xvt_fsys_convert_str_to_fspec(name, &fs);
if (xvt_dm_post_file_save(&fs, TR("Selezionare il file di destinazione")) == FL_OK)
{
xvt_fsys_convert_fspec_to_str(&fs, name.get_buffer(), name.size());
ofstream xls(name);
const char sep = '\t';
TToken_string tab(128, sep);
TString80 str;
int columns = 0;
for (columns = 0; ; columns++)
{
if (s._sheet->head(columns, str))
tab.add(str);
else
break;
}
xls << tab << endl;
for (long n = 0; n < s.items(); n++)
{
const TToken_string& r = s.row(n);
tab = r;
tab.replace(r.separator(), sep);
tab.separator(sep);
for (int c = 0; c < columns; c++)
{
const char ct = s._sheet->column_type(c);
if (ct == 'P' || ct == 'V')
{
tab.get(c, str);
xvt_str_number_format(str.get_buffer(), str.size());
tab.add(str, c);
}
}
xls << tab << endl;
}
xls.close();
xvt_sys_goto_url(name, "open");
}
}
return true;
}
void TSheet::save_columns_order(const TEdit_field& field)
{ sheet().save_columns_order(field); }
void TSheet::set_columns_order(TToken_string* col)
{ sheet().set_columns_order(col); }
void TSheet::load_columns_order(const TEdit_field& field)
{ sheet().load_columns_order(field); }
///////////////////////////////////////////////////////////
// TArray_sheet
///////////////////////////////////////////////////////////
TArray_sheet::TArray_sheet(short x, short y, short dx, short dy, const char* caption,
const char* head, byte buttons, short sht_y)
: TSheet(x, y, dx, dy, caption, head, buttons, sht_y)
{
TToken_string cap(caption);
if (cap.items() > 1)
{
cap.get(0);
FOR_EACH_TOKEN(cap, tok)
create_page(tok, 0);
}
}
// Certified 99%
bool TArray_sheet::destroy(int i)
{
uncheck(-1);
enable_row(-1);
reset_parked();
return _data.destroy(i, TRUE);
}
// @doc EXTERNAL
// @mfunc Aggiunge un elemento allo sheet
//
// @rdesc Ritorna il numero di elementi 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);
const int maxrows=int(items());
for (int r = maxrows-1; r >n ; r--)
{
const bool enab= row_enabled(r);
enable_row(r,row_enabled(r+1));
enable_row(r+1,enab);
}
return n;
}
///////////////////////////////////////////////////////////
// TCursor_sheet
///////////////////////////////////////////////////////////
bool TCursor_sheet::in_key(const TFieldref& fr) const
{
const int logic = _cursor->file().num();
if (fr.file() != 0 && fr.file() != logic)
return false;
const RecDes& rd = prefix().get_recdes(logic);
const int key = _cursor->key();
const KeyDes& kd = rd.Ky[key-1];
for (int i = 0; i < kd.NkFields; i++)
{
const int n = kd.FieldSeq[i] % MaxFields;
if (strcmp(rd.Fd[n].Name, fr.name()) == 0)
return true;
}
return false;
}
TCursor_sheet::TCursor_sheet(TCursor* cursor, const char* fields,
const char* title, const char* head,
byte buttons, short sht_y, WINDOW parent)
: TSheet(sht_y ? 2 : 0, sht_y ? 2 : 0, sht_y ? -2 : 0, sht_y ? -2 : 0,
title, head, buttons, sht_y, parent), _cursor(cursor)
{
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 == ' ')
sheet().align_column(campo, TRUE);
}
_key_cols.set(campo, in_key(fr));
}
}
}
HIDDEN bool _can_post = FALSE;
KEY TCursor_sheet::run()
{
_cursor->freeze(TRUE);
select(_cursor->pos());
_can_post = TRUE;
const KEY k = TSheet::run();
_cursor->freeze(FALSE);
return k;
}
long TCursor_sheet::get_items() const
{ return _cursor ? _cursor->items() : 0; }
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);
}
}
bool TCursor_sheet::get_cell_colors(int row, int col, COLOR& fore, COLOR& back) const
{
if (_key_cols[col])
{
fore = 0;
back = REQUIRED_BACK_COLOR; // Evidenzia i campi chiave
return true;
}
return TSheet::get_cell_colors(row, col, fore, back);
}
///////////////////////////////////////////////////////////
// TBrowse_sheet
///////////////////////////////////////////////////////////
HIDDEN TBrowse_sheet* _cur_browse = NULL;
void TBrowse_sheet::add_custom_filter(const char* regexp)
{
TString filter = _original_filter; // Costruisco il nuovo filtro per estensione del vecchio
if (regexp && *regexp)
{
if (_original_filter.not_empty())
{
filter.insert("(");
filter << ")&&(";
}
filter << regexp;
if (_original_filter.not_empty())
filter << ')';
}
TCursor& c = *cursor();
if (filter != c.filter()) // Cambio il filtro se necessario :-)
{
c.freeze(false);
c.setfilter(filter, true);
c.items(); // Forzo la ricostruzione del cursore
c.freeze(true);
// Forzo un aggiornamento a basso livello
TQuery_field& qf = (TQuery_field&)TMask::field(DLG_QUERY);
XI_OBJ* obj = qf.sheet()->xi_object();
xi_scroll_percent(obj, 100);
xi_scroll_percent(obj, 0);
_sel = 0;
}
}
bool TBrowse_sheet::browse_field_handler(TMask_field& f, KEY k)
{
long rec = -1;
if (k == K_F2)
{
f.reset();
k = K_SPACE;
}
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();
if (b != NULL)
{
b->do_input(FALSE);
rec = b->cursor()->read(_isgteq);
}
}
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); // Non ricordo a cosa serva aggiornare il campo di testo
}
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;
}
bool TBrowse_sheet::filter_handler(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
TString expr; // Espressione di filtro complessiva
if (!f.get().empty()) // Filtro attivato!
{
const short id = f.dlg()-500;
TString e = f.mask().get(id); // Espressione regolare
e.strip("\"'"); // Tolgo caratteri che potrebbero dare problemi
if (!e.blank())
{
const TBrowse& b = *_cur_browse->field().browse();
TToken_string ids = b.get_input_fields();
const int pos = ids.get_pos(id);
if (pos >= 0)
{
TToken_string fns = b.get_input_field_names();
expr << fns.get(pos) << "?=\"" << e << '"';
}
}
if (expr.empty())
f.reset();
}
_cur_browse->add_custom_filter(expr);
}
return true;
}
// @doc EXTERNAL
// @mfunc Gestisce l'handler della finestra
void TBrowse_sheet::handler(
WINDOW win, // @parm Finestra da gestire
EVENT* ep) // @parm Evento da gestire nella finestra
{
switch (ep->type)
{
case E_MOUSE_DOWN:
switch (ep->v.mouse.button )
{
case 1:
{
MENU_ITEM* menu = xvt_res_get_menu(BROWSE_BAR);
if (menu)
{
dictionary_translate_menu(menu);
const PNT& p = ep->v.mouse.where;
RCT cr; xvt_vobj_get_client_rect(win, &cr);
XVT_POPUP_ALIGNMENT pa = XVT_POPUP_CENTER;
if (p.h < cr.right / 3)
pa = XVT_POPUP_LEFT_ALIGN;
else
if (p.h > 2 * cr.right / 3)
pa = XVT_POPUP_RIGHT_ALIGN;
xvt_menu_popup(menu->child, win, p, pa, NULL);
xvt_res_free_menu_tree(menu);
}
return;
}
break;
default:
{
RCT r; sheet().get_rect(r);
if (xvt_rect_has_point(&r, ep->v.mouse.where) && _rec_to_select >= 0)
{
post_select(_rec_to_select);
_rec_to_select = -1;
}
}
break;
}
break;
case E_COMMAND:
switch (ep->v.cmd.tag)
{
case BROWSE_BAR + 1:
save_columns_order(field());
return;
case BROWSE_BAR + 2:
set_columns_order(NULL);
return;
case BROWSE_BAR + 3:
fld(0).on_key(K_F11);
return;
default:
break;
}
break;
case E_CONTROL:
if (ep->v.ctl.ci.type == WC_NOTEBK)
{
const int new_search = ep->v.ctl.ci.v.notebk.tab_no;
on_key(K_CTRL+K_F1+new_search);
return;
}
break;
default:
break;
}
TCursor_sheet::handler(win, ep);
}
#ifndef OLD_FASHIONED_BROWSE
bool lst_handler(TMask_field& lst, KEY k)
{
if (k == K_SPACE)
{
TMask& m = lst.mask();
if (m.is_running())
{
const int sel = atoi(lst.get());
m.on_key(K_CTRL + K_F1 + sel);
}
}
return true;
}
#endif
void TBrowse_sheet::create_key_selector(TToken_string& ca)
{
#ifdef OLD_FASHIONED_BROWSE
set_tab_buttons(ca); // Non funziona piu' bene: cambiamo strada
#else
const int items = ca.items();
if (items > 1)
{
TToken_string co;
for (int i = 0; i < items; i++)
co.add(i);
TList_field& lst = add_list(69, 0, PR("Ordinamento per "), 1, 0, 16, "", co, ca);
lst.set_handler(lst_handler);
}
#endif
}
void TBrowse_sheet::update_key_selector(int sel)
{
#ifdef OLD_FASHIONED_BROWSE
show_page(sel);
#else
if (id2pos(69) >= 0) // Has been created?
set(69, sel, 0); // Don't fire any events!
#endif
}
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() ? f.browse()->input_fields()+1 : 1),
_field(f), _sel(0), _original_filter(cursor->filter())
{
const bool normal = f.browse() != NULL && sibling.full();
TToken_string ca; // Tag buttons
if (normal) // normal mask query
{
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);
}
}
else // ABnormal application query: F9 or F8 handler!
{
ca = f.prompt();
if (ca.blank())
ca = TR("Codice");
}
create_key_selector(ca);
TToken_string tids = head;
TToken_string tfns = fields;
TToken_string ids, fns;
if (f.browse() != NULL)
{
ids = f.browse()->get_input_fields();
fns = f.browse()->get_input_field_names();
}
TEditable_field* e = NULL;
#ifdef OLD_FASHIONED_BROWSE
int y = 0;
#else
int y = 1;
#endif
bool first = true;
for (const char* i = ids.get(0); i; i = ids.get())
{
if (*i != '\0' && *i != '"' && strchr(i, '@') == NULL)
{
const short id = f.atodlg(i);
const TMask_field& c = f.mask().field(id);
if (c.is_editable() && c.active())
{
int pos = ids.get_pos(id);
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();
int a;
// Toglie spazi e simboli iniziali dal prompt
for (a = 0; p[a] && !isalnum(p[a]); a++);
p.ltrim(a);
}
p.left_just(16);
TString8 flags;
if (c.roman()) flags << 'M';
if (c.right_justified()) flags << 'R';
if (c.uppercase()) flags << 'U';
if (c.zerofilled()) flags << 'Z';
if (!normal) flags << 'D'; // Disable ABnormal fields
const int csize = c.size();
switch (c.class_id())
{
case CLASS_EDIT_FIELD:
{
const int sz = csize > 50 ? 50 : csize; // Dimensione del campo di ricerca
e = &add_string(c.dlg(), 0, p, 1, y++, csize, flags, sz);
// Aggiunge campo con le icone di filtraggio
add_checkbutton(c.dlg()+500, 0, "", sz+strlen(p)+ 2, y-1, 2, 1, "", 10112, 10113).set_handler(filter_handler);
}
break;
case CLASS_ZOOM_FIELD:
{
e = &add_string(c.dlg(), 0, p, 1, y++, 32000, flags, 50);
// Aggiunge campo con le icone di filtraggio
add_checkbutton(c.dlg()+500, 0, "", 52 + strlen(p), y-1, 2, 1, "", 10112, 10113).set_handler(filter_handler);
}
break;
case CLASS_REAL_FIELD:
e = &add_number(c.dlg(), 0, p, 1, y++, csize, flags);
break;
case CLASS_DATE_FIELD:
e = &add_date(c.dlg(), 0, p, 1, y++, flags);
break;
default:
e = NULL;
break;
}
if (e != NULL && normal)
{
e->set_handler(browse_field_handler);
e->set(c.get());
if (e->dlg() == f.dlg() || first)
{
first_focus(e->dlg());
first = false;
}
}
}
}
}
if (e != NULL && normal)
e->set_handler(last_browse_field_handler);
// carica ordine colonne anche per ricerche costruite run-time
load_columns_order(f);
}
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;
update_key_selector(_sel);
const KEY key = TCursor_sheet::run();
_cur_browse = NULL;
return key;
}