07f592bd22
git-svn-id: svn://10.65.10.50/branches/R_10_00@23139 c028cbd2-c16b-5b4b-a496-9718f37d4682
2133 lines
56 KiB
C++
Executable File
2133 lines
56 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 <dongle.h>
|
|
#include <relation.h>
|
|
#include <sheet.h>
|
|
#include <toolfld.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
#include <xml.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]; }
|
|
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 tot_width = f_width;
|
|
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'; else
|
|
if (wi.find('D') >= 0)
|
|
_type[i] = 'D';
|
|
|
|
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);
|
|
|
|
tot_width += v_width[i];
|
|
if (tot_width > 2048) // Taglio corto con gli sheet enormi > 16000 pixel
|
|
break;
|
|
}
|
|
|
|
// Calcola rettangolo massimo per lo sheet
|
|
XI_OBJ* itf = get_interface(parent);
|
|
const XI_RCT rct = coord2rct(itf, x, y, -2, -2);
|
|
|
|
// Controlla se ci sono troppe colonne fisse
|
|
if ((f_width+max_width)*XI_FU_MULTIPLE > rct.right)
|
|
fixed_columns = 1;
|
|
|
|
|
|
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
|
|
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(xi_get_system_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 (i == 0 && _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;
|
|
}
|
|
}
|
|
|
|
// Attenzione: negli sheet molto grandi succede che rd.right < 0
|
|
XI_RCT rd; xi_get_def_rect(listdef, &rd);
|
|
if (rd.right < 0 || (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++)
|
|
{
|
|
XI_RCT rct; xi_get_rect(column[i], &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
|
|
{
|
|
int num = 0;
|
|
const long* handle = xi_get_list_info(_obj, &num);
|
|
const long tot = items();
|
|
bool scroll_first = tot == 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 > tot;
|
|
}
|
|
|
|
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);
|
|
_obj->v.list->focus_cell->v.cell.row = newrow;
|
|
}
|
|
}
|
|
|
|
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 == 1) // 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 = col == 0 ? checked(rec) : row(rec).get_char(col) > '0';
|
|
xiev->v.cell_request.icon_rid = on ? ICO_CHECK_ON : ICO_CHECK_OFF;
|
|
}
|
|
break;
|
|
case 'M': // Set value for "roman" cell
|
|
src = itor(row(rec).get_int(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;
|
|
*/
|
|
_sheet->post_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)
|
|
{
|
|
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, TOOL_OK);
|
|
|
|
if (check_enabled())
|
|
{
|
|
add_button(DLG_USER, TR("~Tutti"), 0, TOOL_MULTISEL);
|
|
set_handler(DLG_USER, tutti_handler);
|
|
}
|
|
|
|
if (buttons & 0x01) add_button(DLG_LINK, TR("Colle~ga"), K_CTRL+'G', TOOL_LINK);
|
|
if (buttons & 0x02) add_button(DLG_NEWREC, TR("~Nuovo"), K_INS, TOOL_NEWREC);
|
|
if (buttons & 0x04) add_button(DLG_DELREC, TR("~Elimina"), K_DEL, TOOL_DELREC);
|
|
|
|
add_button(DLG_EXPORT, TR("~Excel"), 0, TOOL_EXCEL);
|
|
set_handler(DLG_EXPORT, export_handler);
|
|
|
|
if (buttons & 0x20)
|
|
{
|
|
add_button(DLG_EDIT, TR("~Filtro"), K_CTRL+'F', TOOL_ELABORA);
|
|
set_handler(DLG_EDIT, filtro_handler);
|
|
}
|
|
|
|
if (buttons & 0x08) add_button(DLG_QUIT, "Fine", K_ESC, TOOL_QUIT);
|
|
else add_button(DLG_CANCEL, "Annulla", K_ESC, TOOL_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 (id > 0 && 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()
|
|
if (btnwin != NULL_WIN)
|
|
{
|
|
int buttons = 0;
|
|
RCT br;
|
|
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)
|
|
{
|
|
RCT wr; 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);
|
|
RCT wr; xvt_vobj_get_client_rect(s.parent(), &wr);
|
|
RCT br; 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 long imax = items();
|
|
const bool on = imax > 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 >= imax)
|
|
i = 0;
|
|
for (; i < imax && row_disabled(i); i++);
|
|
if (i >= 0 && i < imax && i != selected())
|
|
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':
|
|
if (items() && id2pos(DLG_SAVEREC) >= 0)
|
|
export_handler(field(DLG_SAVEREC), K_SPACE);
|
|
break;
|
|
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+'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)
|
|
{
|
|
if (_select_row < items())
|
|
{
|
|
const short focus_id = low_get_focus_id(curr_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;
|
|
}
|
|
|
|
static TString& clean_white_space(TString& str)
|
|
{
|
|
str.trim();
|
|
char* buff = str.get_buffer();
|
|
for (char* b = buff; *b; b++)
|
|
{
|
|
if (*b > '\0' && *b < ' ')
|
|
*b = ' ';
|
|
}
|
|
str.strip_double_spaces();
|
|
return str;
|
|
}
|
|
|
|
bool TSheet::export_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TSheet& s = (TSheet&)f.mask();
|
|
TString caption; s.get_caption(caption);
|
|
for (char* buf = caption.get_buffer(); *buf; buf++)
|
|
{
|
|
switch (*buf)
|
|
{
|
|
case '?':
|
|
case '(':
|
|
case ')':
|
|
case '/':
|
|
case '\\':
|
|
case '*': *buf = ' '; break;
|
|
default : break;
|
|
}
|
|
}
|
|
if (caption.blank())
|
|
caption = main_app().title();
|
|
|
|
TString cap = caption; cap.strip_spaces();
|
|
TFilename name;
|
|
name.tempdir(); name.add(cap); name.ext("xls");
|
|
if (name.full()) // Dummy test
|
|
{
|
|
ofstream xls(name);
|
|
|
|
xls << "<html>" << endl;
|
|
save_html_head(xls, caption);
|
|
xls << "<body>" << endl;
|
|
xls << " <table border=\"1\">" << endl;
|
|
xls << " <caption>" << caption << "</caption>" << endl;
|
|
xls << " <thead>" << endl;
|
|
|
|
int columns = 0;
|
|
XI_OBJ** pcols = xi_get_member_list(s._sheet->xi_object(), &columns);
|
|
|
|
for (int c = 1; c < columns; c++)
|
|
{
|
|
const int idx = pcols[c]->cid - 1101;
|
|
const char ct = s._sheet->column_type(idx);
|
|
TXmlItem col; col.SetTag("col");
|
|
switch (ct)
|
|
{
|
|
case 'C': col.SetAttr("align", "center"); break;
|
|
case 'D': col.SetAttr("style", "mso-number-format:\\Short Date"); break;
|
|
case 'P':
|
|
case 'R':
|
|
case 'V': col.SetAttr("align", "right"); break;
|
|
default : col.SetAttr("style", "mso-number-format:\\@"); break;
|
|
}
|
|
col.Write(xls, 3);
|
|
xls << endl;
|
|
}
|
|
|
|
TXmlItem tr; tr.SetTag("tr");
|
|
tr.SetColorAttr("bgcolor", BTN_BACK_COLOR);
|
|
tr.Write(xls, 3);
|
|
xls << endl;
|
|
|
|
TString str;
|
|
for (int c = 1; c < columns; c++)
|
|
{
|
|
xi_get_text(pcols[c], str.get_buffer(), str.size());
|
|
xls << " <th>" << clean_white_space(str) << "</th>" << endl;
|
|
}
|
|
xls << " </tr>" << endl;
|
|
xls << " </thead>" << endl;
|
|
xls << " <tbody>" << endl;
|
|
for (long i = 0; i < s.items(); i++)
|
|
{
|
|
const TToken_string& r = s.row(i);
|
|
xls << " <tr>" << endl;
|
|
for (int c = 1; c < columns; c++)
|
|
{
|
|
xls << " <td>";
|
|
const int idx = pcols[c]->cid - 1101;
|
|
r.get(idx, str);
|
|
clean_white_space(str);
|
|
if (str.full())
|
|
{
|
|
const char ct = s._sheet->column_type(idx);
|
|
switch (ct)
|
|
{
|
|
case 'D':
|
|
if (str.len() == 8)
|
|
{
|
|
const TDate d(atol(str));
|
|
str = d.stringa();
|
|
}
|
|
break;
|
|
case 'P':
|
|
case 'V':
|
|
xvt_str_number_format(str.get_buffer(), str.size());
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
xls << str;
|
|
}
|
|
xls << "</td>" << endl;
|
|
}
|
|
xls << " </tr>" << endl;
|
|
}
|
|
xls << " </tbody>" << endl;
|
|
xls << " </table>" << endl;
|
|
xls << "</body>" << endl;
|
|
xls << "</html>" << endl;
|
|
}
|
|
if (name.exist())
|
|
xvt_sys_goto_url(name, "open");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TSheet::filter_dialog()
|
|
{ return sorry_box("Filtro non attivabile"); }
|
|
|
|
bool TSheet::filtro_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TSheet& s = (TSheet&)f.mask();
|
|
s.filter_dialog();
|
|
return false;
|
|
}
|
|
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);
|
|
if (n >= 0 && s[0]=='X' && check_enabled())
|
|
check(n);
|
|
return n;
|
|
}
|
|
|
|
long TArray_sheet::add(TToken_string* s)
|
|
{
|
|
const long n = _data.add(s);
|
|
if (n >= 0 && (*s)[0]=='X' && check_enabled())
|
|
check(n);
|
|
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 ? 3 : 0, sht_y ? 3 : 0, sht_y ? -3 : 0, sht_y ? -3 : 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)
|
|
{
|
|
const 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 = (const 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);
|
|
}
|
|
|
|
bool TCursor_sheet::filter_dialog()
|
|
{
|
|
TRectype rec = _cursor->curr();
|
|
const RecDes& rd = rec.rec_des();
|
|
const KeyDes& k0 = rd.Ky[0];
|
|
const int kfields = k0.NkFields;
|
|
|
|
TMask m(TR("Filtro"), 1, 78, kfields+5);
|
|
m.add_button_tool(DLG_OK, "", TOOL_OK);
|
|
m.add_button_tool(DLG_CANCEL, "", TOOL_CANCEL);
|
|
for (int i = 0; i < kfields; i++)
|
|
{
|
|
const int nf = k0.FieldSeq[i] % MaxFields;
|
|
const char* fname = rec.fieldname(nf);
|
|
const TFieldtypes ft = rec.type(fname);
|
|
TString16 prompt = fname; prompt.left_just(12);
|
|
TString4 flags;
|
|
switch (ft)
|
|
{
|
|
case _alfafld:
|
|
case _charfld:
|
|
m.add_string(101+i, 0, prompt, 1, i+1, rec.length(fname), flags).set_field(fname);
|
|
break;
|
|
case _intzerofld:
|
|
case _longzerofld:
|
|
flags << "Z";
|
|
case _wordfld:
|
|
case _intfld:
|
|
case _longfld:
|
|
m.add_number(101+i, 0, prompt, 1, i+1, rec.length(fname), flags).set_field(fname);
|
|
break;
|
|
case _datefld:
|
|
m.add_date(101+i, 0, prompt, 1, i+1, flags).set_field(fname);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < kfields-1; i++)
|
|
{
|
|
const int nf = k0.FieldSeq[i] % MaxFields;
|
|
const char* fname = rec.fieldname(nf);
|
|
TMask_field* f = m.find_by_fieldname(fname);
|
|
if (f)
|
|
f->set(rec.get(fname));
|
|
}
|
|
|
|
if (m.run() == K_ENTER)
|
|
{
|
|
rec.zero();
|
|
for (int i = 0; i < kfields; i++)
|
|
{
|
|
const int nf = k0.FieldSeq[i] % MaxFields;
|
|
const char* fname = rec.fieldname(nf);
|
|
const TMask_field* f = m.find_by_fieldname(fname);
|
|
if (f) rec.put(fname, f->get());
|
|
}
|
|
|
|
TWait_cursor hourglass;
|
|
_cursor->freeze(false);
|
|
_cursor->setregion(rec, rec);
|
|
_cursor->items();
|
|
_cursor->freeze(true);
|
|
force_update();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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
|
|
long 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:
|
|
{
|
|
RCT r; sheet().get_rect(r);
|
|
if (xvt_rect_has_point(&r, ep->v.mouse.where))
|
|
{
|
|
MENU_ITEM* menu = xvt_res_get_menu(BROWSE_BAR);
|
|
if (menu)
|
|
{
|
|
dictionary_translate_menu(menu);
|
|
xvt_menu_popup(menu->child, win, ep->v.mouse.where, XVT_POPUP_LEFT_ALIGN, NULL);
|
|
xvt_res_free_menu_tree(menu);
|
|
return 0L; // no default handling!
|
|
}
|
|
}
|
|
}
|
|
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-BROWSE_BAR)
|
|
{
|
|
case 1:
|
|
save_columns_order(field());
|
|
return 0L;
|
|
case 2:
|
|
set_columns_order(NULL);
|
|
return 0L;
|
|
case 3:
|
|
fld(0).on_key(K_F11);
|
|
return 0L;
|
|
case 4:
|
|
on_key(K_CTRL + 'E');
|
|
return 0L;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TCursor_sheet::handler(win, ep);
|
|
}
|
|
|
|
static bool keysel_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;
|
|
}
|
|
|
|
#define DLG_KEY_SELECTOR 69
|
|
|
|
void TBrowse_sheet::create_key_selector(TToken_string& ca)
|
|
{
|
|
const int items = ca.items();
|
|
if (items > 1)
|
|
{
|
|
TToken_string co(3*items);
|
|
for (int i = 0; i < items; i++)
|
|
co.add(i);
|
|
TList_field& lst = add_list(DLG_KEY_SELECTOR, 0, PR("Ordinamento per "), 1, 0, 16, "", co, ca);
|
|
lst.set_handler(keysel_handler);
|
|
}
|
|
}
|
|
|
|
void TBrowse_sheet::update_key_selector(int sel)
|
|
{
|
|
TMask_field* ks = find_by_id(DLG_KEY_SELECTOR);
|
|
if (ks != NULL) // Has been created?
|
|
ks->set(sel); // Don't fire any events!
|
|
}
|
|
|
|
TBrowse_sheet::TBrowse_sheet(TCursor* cursor, const char* fields,
|
|
const char* title, const char* head, byte buttons,
|
|
TEdit_field& f, TToken_string& sibling, CONTROL_HANDLER custom_filter_handler)
|
|
: TCursor_sheet(cursor, fields, title, head, buttons,
|
|
f.browse() ? f.browse()->input_fields()+1 : 1),
|
|
_field(f), _sel(0), _original_filter(cursor->filter()),
|
|
_custom_filter_handler(custom_filter_handler)
|
|
|
|
{
|
|
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;
|
|
int y = 1;
|
|
|
|
bool first = true;
|
|
|
|
FOR_EACH_TOKEN(ids, i)
|
|
{
|
|
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+p.len()+ 2, y-1, 2, 1, "", 10112, 10113).set_handler(_custom_filter_handler != NULL ? _custom_filter_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 + p.len(), y-1, 2, 1, "", 10112, 10113).set_handler(_custom_filter_handler != NULL ? _custom_filter_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 TCursor_sheet::on_key(k);
|
|
}
|
|
|
|
KEY TBrowse_sheet::run()
|
|
{
|
|
_cur_browse = this;
|
|
update_key_selector(_sel);
|
|
|
|
TMask_field* f = find_by_id(field().dlg());
|
|
if (f && !f->empty())
|
|
browse_field_handler(*f, K_SPACE); // Posizione iniziale
|
|
const KEY key = TCursor_sheet::run();
|
|
_cur_browse = NULL;
|
|
return key;
|
|
}
|