campo-sirio/include/sheet.cpp
guy 6d79069eb6 Gestione tasti rapidi.
git-svn-id: svn://10.65.10.50/trunk@52 c028cbd2-c16b-5b4b-a496-9718f37d4682
1994-08-23 13:52:36 +00:00

734 lines
16 KiB
C++
Executable File

#include <mask.h>
#include <applicat.h>
#include <colors.h>
#include <relation.h>
#include <printer.h>
#include <sheet.h>
#include <urldefid.h>
TSheet::TSheet(short x, short y, short dx, short dy,
const char* title, const char* head, byte buttons,
long first, WINDOW parent)
: _curr(first), _last_update(-1), _checkable(FALSE),
_check_enabled(TRUE), _buttonmask(buttons)
{
const char* g;
TToken_string new_head(512);
TToken_string h(head);
TString item(80);
for(_columns = 0; (g = h.get()) != NULL; _columns++)
{
CHECK(_columns < MAX_COL, "To many columns in sheet ");
item = g;
const int et = item.find('@');
if (et >= 0)
{
_size[_columns] = atoi(item.mid(et+1));
item.cut(et);
if (_columns == 0 && et == 0)
_checkable = _size[0] == 1;
} else _size[_columns] = item.len();
item.trim();
new_head.add(item);
}
set_row(new_head, -1);
for (int i = 0; i < MAX_BUT; i++) _button[i] = NULL_WIN;
if (parent == NULL_WIN) parent = TASK_WIN;
long flags = WSF_CLOSE | WSF_SIZE | WSF_VSCROLL | WSF_HSCROLL ;
WIN_TYPE wt = W_DOC;
if (parent != TASK_WIN)
{
wt = W_PLAIN;
flags = WSF_VSCROLL;
}
if (dx == 0) // Calculates window width
{
RCT r; get_client_rect(parent, &r);
dx = r.right/CHARX -6;
const int larg = width();
if (dx > larg) dx = larg;
}
if (dy == 0) dy = 20; // Calculates window height
create(x, y, dx, dy, title, flags, wt, parent);
if (wt != W_PLAIN) // If normal sheet add buttons
{
_visible_rows = rows()- head_on() - 3;
add_button(DLG_SELECT, "Selezione" );
if (buttons & 0x1) add_button(DLG_NEWREC, "Gestione");
if (buttons & 0x2) add_button(DLG_NEWREC, "Nuovo");
if (buttons & 0x4) add_button(DLG_DELREC, "Elimina");
if (buttons & 0x8) add_button(DLG_QUIT, "Fine");
else add_button(DLG_CANCEL, "Annulla");
}
}
void TSheet::add_button(short id, const char* caption, KEY key)
{
const int BUT_HEIGHT =
#if XVT_OS == XVT_OS_WIN
2
#else
1
#endif
;
WINDOW b = xvt_create_control(WC_PUSHBUTTON, 0, 0, 11, BUT_HEIGHT, caption, win(), 0, 0, id);
for (int i = 0; i < MAX_BUT; i++)
if (_button[i] == NULL_WIN)
{
_button[i] = b;
_key[i] = key;
break;
}
}
void TSheet::repos_buttons() const
{
for (int buttons = 0; _button[buttons] != NULL_WIN; buttons++)
if (buttons == MAX_BUT-1) { buttons++; break; }
if (buttons == 0) return;
RCT wr; get_client_rect(win(), &wr);
RCT br; get_client_rect(_button[0], &br);
int space = (wr.right - buttons * br.right) / (buttons+1);
if (space < 0) space = 0;
int x = space;
const int y = wr.bottom - br.bottom-4;
for (int b = 0; b < buttons; b++, x += br.right+space)
{
RCT r; set_rect(&r, x, y, x+br.right, y+br.bottom);
move_window(_button[b], &r);
}
}
void TSheet::open()
{
set_scroll_max(width(), items());
_last_update = -1;
if (!is_visible(_curr)) set_first(_curr);
if (buttons_on())
{
// Abilita selezione se c'e' almeno un elemento
xvt_enable_control(_button[0], items() > 0);
repos_buttons();
}
TScroll_window::open();
force_update();
}
void TSheet::set_first(long n)
{
update_thumb(-1, n);
}
void TSheet::set_row(const TToken_string& row, byte i)
{
if (i > 64) i = 0; else i++;
if (_page.objptr(i) == NULL)
_page.add(row, i);
else
((TToken_string&)_page[i]) = row;
}
void TSheet::build_page(long from)
{
const long f = (from < 0) ? first() : from;
if (_last_update != f)
{
int r = visible_rows();
if (f+r > items())
r = int(items()-f);
if (r > 0)
page_build(f, r);
_last_update = f;
}
}
short TSheet::reserved_rows() const
{
return buttons_on() ? 3 : 0;
}
void TSheet::handler(WINDOW win, EVENT* ep)
{
switch(ep->type)
{
case E_FOCUS:
invert_row(selected());
break;
case E_MOUSE_DOWN:
if (ep->v.mouse.button)
{
dispatch_e_char(win, K_ESC);
return;
}
case E_MOUSE_DBL:
{
const short y = ep->v.mouse.where.v / CHARY;
const short f = head_on() ? 1 : 0;
if (y >= f)
{
long vec = selected();
long nuo = first()+y-f;
select(nuo);
if (ep->type == E_MOUSE_DBL)
dispatch_e_char(win, K_ENTER);
else if (_checkable && _check_enabled && vec == nuo)
{
_checked.not(nuo);
force_update();
}
}
else
dispatch_e_char(win, y ? K_UP : K_PREV);
}
break;
case E_CONTROL:
switch(ep->v.ctl.id)
{
case DLG_OK :
case DLG_SELECT:dispatch_e_char(win, K_ENTER); break;
case DLG_CANCEL:
case DLG_QUIT :dispatch_e_char(win, K_ESC); break;
case DLG_NEWREC:dispatch_e_char(win, K_INS); break;
case DLG_DELREC:dispatch_e_char(win, K_DEL); break;
default:
{
const WINDOW b = ep->v.ctl.ci.win;
for (int i = 0; i < MAX_BUT; i++)
if (_button[i] == b)
{
stop_run(_key[i]);
break;
}
break;
}
}
break;
case E_SIZE:
{
_last_update = -1;
_visible_rows = ep->v.size.height/CHARY - (head_on() ? 1 : 0);
if (buttons_on())
{
_visible_rows -= reserved_rows();
repos_buttons();
}
force_update();
}
break;
default:
break;
}
TScroll_window::handler(win, ep);
}
PNT TSheet::log2dev(long x, long y) const
{
if (autoscrolling()) x -= origin().x;
return TWindow::log2dev(x, y);
}
bool TSheet::on_key(KEY key)
{
switch(key)
{
case K_ENTER:
if (items() < 1) key = K_ESC;
case K_ESC:
stop_run(key);
case K_DEL:
if ((_buttonmask & 0x4) && items())
stop_run(key);
break;
case K_INS:
if (_buttonmask & 0x3)
stop_run(K_INS);
break;
case K_LHOME:
select(0);
return TRUE;
case K_LEND:
select(items()-1);
return TRUE;
case K_PREV:
select(selected()-visible_rows());
return TRUE;
case K_UP:
select(selected()-1);
return TRUE;
case K_NEXT:
select(selected()+visible_rows());
return TRUE;
case K_DOWN:
select(selected()+1);
return TRUE;
case K_CTRL+'P':
print();
break;
default:
for (int i = 0; i < MAX_BUT; i++)
if (_key[i] == key)
{
stop_run(key);
break;
}
break;
}
if (_checkable && _check_enabled && items() > 0)
{
bool ok = TRUE;
switch(key)
{
case K_SPACE: _checked.not(selected()); break;
case K_F2 : uncheck(-1); break;
case K_F3 : check(-1); break;
default : ok = FALSE; break;
}
if (ok) force_update();
}
return TScroll_window::on_key(key);
}
void TSheet::select(long n)
{
if (n < 0) n = 0; else
if (n >= items()) n = items()-1;
invert_row(_curr);
_curr = n;
if (is_visible(_curr))
invert_row(_curr);
else
{
const long s = (_curr < first()) ? _curr : _curr-visible_rows()+1;
set_first(s);
force_update();
}
}
void TSheet::check(long n, bool on)
{
if (n < 0)
{
if (on)
{
_checked.set(items()-1); // Force the size of Bit_array
_checked.set();
}
else
_checked.reset();
}
else
_checked.set(n, on);
}
// Converte il numero di riga assoluto nell'indice dell'array _page
int TSheet::row_to_page(long n) const
{
long i = (n < 0) ? 0L : n-first()+1;
if (i < 0 || i > visible_rows())
{
error_box("Line out of screen");
i = 0L;
}
return (int)i;
}
// Converte il numero di riga assoluto nella coordinata y sulla finestra
int TSheet::row_to_win(long n) const
{
int y = row_to_page(n);
if (y < 1) y = 0; else
if (!head_on()) y--;
return y;
}
// Calcola la larghezza totale dello sheet virtuale
int TSheet::width() const
{
int width = 0;
for (int c = 0; c < _columns; c++)
width += _size[c]+(c > 0);
return width;
}
void TSheet::invert_row(long n)
{
if (win() != NULL_WIN && is_visible(n))
{
const short y = row_to_win(n);
autoscroll(FALSE);
invert_bar(0,y,columns(),y+1);
autoscroll(TRUE);
}
}
bool TSheet::update_row(long n)
{
const int i = row_to_page(n);
if (i >= _page.items()) return FALSE;
TToken_string& t = (TToken_string&)(_page[i]);
t.restart();
const short y = row_to_win(n);
const char* s;
int x = 0;
for (int j = 0; (s = t.get()) != NULL; x += _size[j++]+1)
{
int x1 = x;
if (n < 0) // Centra le testate
x1 += (_size[j]-strlen(s)) / 2;
else
if (_checkable && j == 0)
s = _checked[n] ? "X" : " ";
stringat(x1, y, s);
}
return TRUE;
}
TToken_string& TSheet::row(long n)
{
if (n < 0) n = selected();
if (!is_visible(n))
{
build_page(n);
set_first(n);
}
short idx = row_to_page(n);
return (TToken_string&)_page[idx];
}
void TSheet::update()
{
if (_last_update < 0)
{
set_color(COLOR_BLACK, COLOR_WHITE);
set_brush(COLOR_WHITE);
set_pen(COLOR_BLACK);
set_font(FF_FIXED);
_visible_rows = rows() - reserved_rows() - head_on();
}
if (head_on())
{
const int height = visible_rows()+1;
const int width = columns()+1;
short x = -1;
for (int c = 0; c < _columns; c++)
{
x += _size[c] + 1;
line(x,0,x,height);
}
autoscroll(FALSE);
set_brush(MASK_BACK_COLOR);
bar(0,0,width,1);
if (buttons_on())
bar(0, height, width, height+reserved_rows()+1);
autoscroll(TRUE);
}
build_page();
if (head_on()) update_row(-1);
long last = first() + visible_rows();
if (last > items()) last = items();
for (long n = first(); n < last; n++) update_row(n);
if (get_front_window() == win())
invert_row(selected());
}
void TSheet::print()
{
TPrinter& pr = MainApp()->printer();
TPrintrow row;
bool ok = pr.open();
set_cursor(TASK_WIN, CURSOR_WAIT);
int step = visible_rows();
for (long n = 0L; ok && n < items(); n += step)
{
set_first(n);
build_page();
if ((n+step) > items()) step = int(items()-n);
for (int i = 1; ok && i <= step; i++)
{
const char* s;
TToken_string& t = (TToken_string&)_page[i];
t.restart();
row.reset();
for (int j = 0, x = 0; (s = t.get()) != NULL; x += _size[j++]+1)
row.put(s, x);
ok = pr.print(row);
}
}
set_cursor(TASK_WIN, CURSOR_ARROW);
if (ok)
{
pr.formfeed();
pr.close();
}
set_focus();
}
///////////////////////////////////////////////////////////
// TArray_sheet
///////////////////////////////////////////////////////////
TArray_sheet::TArray_sheet(short x, short y, short dx, short dy,
const char* caption, const char* head, byte buttons, WINDOW parent)
: TSheet(x, y, dx, dy, caption, head, buttons, 0L, parent)
{}
void TArray_sheet::page_build(long first, byte num)
{
for (byte i = 0; i < num; i++)
set_row(data(first+i), i);
}
long TArray_sheet::add(const TToken_string& s)
{
const long n = _data.add(s, -1);
set_scroll_max(-1, n);
return n;
}
long TArray_sheet::insert(const TToken_string& s, long n)
{
_data.insert(s, (int)n);
set_scroll_max(-1, items());
return n;
}
///////////////////////////////////////////////////////////
// TCursor_sheet
///////////////////////////////////////////////////////////
TCursor_sheet::TCursor_sheet(TCursor* cursor, const char* fields,
const char* title, const char* head, byte buttons)
: TSheet(-1,-1, 0, 0, title,head,buttons,cursor->pos()),
_cursor(cursor), _records(cursor->items())
{
TToken_string fldlst(fields);
int campi = 0;
for (const char* t = fldlst.get(); t; t = fldlst.get(), campi++)
if (*t > ' ' && *t != '\"')
{
TFieldref fr(t, 0);
TRecfield* rf = new TRecfield(_cursor->curr(fr.file()),
fr.name(), fr.from(), fr.to() - 1);
_fields.add(rf, campi);
}
}
KEY TCursor_sheet::run()
{
_records = _cursor->items();
_cursor->freeze(TRUE);
const KEY k = TSheet::run();
_cursor->freeze(FALSE);
return k;
}
void TCursor_sheet::page_build(long first, byte rows)
{
TToken_string l(256);
*_cursor = (TRecnotype)first;
for (byte r = 0; r < rows; r++, ++(*_cursor))
{
l.cut(0);
const int last = _fields.last();
for (int i = 0; i <= last; i++)
{
TRecfield* rf = (TRecfield*)_fields.objptr(i);
TFixed_string s(rf ? (const char*)*rf : "");
l.add(s);
}
set_row(l, r);
}
}
///////////////////////////////////////////////////////////
// TBrowse_sheet
///////////////////////////////////////////////////////////
TBrowse_sheet::TBrowse_sheet(TCursor* cursor, const char* fields,
const char* title, const char* head, byte buttons,
TEdit_field* f, TToken_string* s)
: TCursor_sheet(cursor, fields, title, head, buttons), _field(f)
{
xvt_create_control(WC_EDIT, 1, -3, f->size()+1, 1, f->get(), win(),
CTL_FLAG_DISABLED, 0L, 100);
if (s)
{
WINDOW listbox = xvt_create_control(WC_LISTBUTTON, f->size()+3, -3, 18, 3,
"", win(), 0, 0L, 99);
SLIST lst = slist_new();
for (const char* item = s->get(0); item; item = s->get())
{
item = s->get();
slist_add(lst, (SLIST_ELT)NULL, (char*)item, 0L);
}
win_list_add(listbox, -1, (char*)lst);
slist_dispose(lst);
TString id(3); id << f->dlg();
const int sel = s->get_pos(id) >> 1;
win_list_set_sel(listbox, sel, TRUE);
}
}
short TBrowse_sheet::reserved_rows() const
{
return TSheet::reserved_rows() + 1;
}
void TBrowse_sheet::repos_buttons() const
{
TSheet::repos_buttons();
RCT wr; get_client_rect(win(), &wr);
for (int id = 99; id <= 100; id++)
{
WINDOW w = get_ctl_window(win(), id);
if (w != NULL_WIN)
{
RCT r; get_client_rect(w, &r);
r.left = CHARX*(id == 99 ? 1 : 21);
r.top = wr.bottom - 4*CHARY + 4;
r.right += r.left;
r.bottom += r.top;
move_window(w, &r);
}
}
}
bool TBrowse_sheet::on_key(KEY k)
{
WINDOW ctl = get_ctl_window(win(), 100);
const bool alnum = (k >= '0' && k <= '9') ||
(k >= 'A' && k <= 'Z') ||
(k >= 'a' && k <= 'z') ||
k == ' ';
if (alnum || k == K_BACKSPACE || k == K_DEL)
{
const long oldsel = selected();
const TString old(_field->get());
TString val(old.size()+1); val = old;
if (alnum) val << char(k);
else val.rtrim(1);
field().set(val);
((TBrowse*)field().browse())->do_input(FALSE);
_cursor->read();
if (_cursor->file()->bad())
{
beep();
field().set(val = old);
*_cursor = oldsel;
}
else
select(_cursor->pos());
if (ctl != NULL_WIN) set_title(ctl, (char*)(const char*)field().get());
return TRUE;
}
else
{
field().reset();
if (ctl != NULL_WIN) set_title(ctl, "");
}
return TSheet::on_key(k);
}
void TBrowse_sheet::handler(WINDOW win, EVENT* ep)
{
if (ep->type == E_CONTROL && ep->v.ctl.id == 99)
{
const int what = win_list_get_sel_index(ep->v.ctl.ci.win);
if (what >= 0)
stop_run(K_CTRL + what);
else
set_front_window(win);
return;
}
TCursor_sheet::handler(win, ep);
}
KEY TBrowse_sheet::run()
{
const bool spork = field().dirty(); // Store field status
const TString old(field().get());
const KEY key = TCursor_sheet::run();
if (key == K_ESC || key == K_F9 || key == K_INS)
{
field().set(old); // Restore field status
field().set_dirty(spork);
}
return key;
}