campo-sirio/ba/ba0102.cpp

800 lines
17 KiB
C++
Raw Normal View History

#include <math.h>
#include <mask.h>
#include <urldefid.h>
#include <utility.h>
#include "ba0102.h"
///////////////////////////////////////////////////////////
// TMenu_tree
///////////////////////////////////////////////////////////
const TSubmenu& TMenu_tree::curr_submenu() const
{
CHECKS(_submenu, "NULL submenu ", (const char*)_curr_id);
return *_submenu;
}
const TMenuitem& TMenu_tree::curr_item() const
{
const TSubmenu& sm = curr_submenu();
if (_menuitem < 0 || _menuitem >= sm.items())
{
NFCHECK("Invalid submenu item %d in %s", _menuitem, (const char*)sm.name());
return sm.item(0);
}
return sm.item(_menuitem);
}
struct TFind_node_data
{
TString _id;
size_t _count;
};
struct TFind_string_data
{
TString _str;
TAssoc_array* _ignore_list;
};
HIDDEN bool find_string_callback(TTree& tree, void* jolly, word flags)
{
if (flags == SCAN_PRE_ORDER)
{
TMenu_tree& mt = (TMenu_tree&)tree;
const TSubmenu& sm = mt.curr_submenu();
if (sm.disabled())
return FALSE;
TFind_string_data& data = *(TFind_string_data*)jolly;
if (data._ignore_list->is_key(sm.name()))
return FALSE;
TString desc; mt.get_description(desc);
desc.upper();
if (desc.find(data._str) >= 0 || desc.match(data._str))
return TRUE;
}
return FALSE;
}
HIDDEN bool find_node_callback(TTree& tree, void* jolly, word flags)
{
if (flags == SCAN_PRE_ORDER)
{
TFind_node_data& data = *(TFind_node_data*)jolly;
data._count++;
TString id; tree.curr_id(id);
if (id == data._id)
return TRUE;
}
return FALSE;
}
HIDDEN bool find_leaf_callback(TTree& tree, void* jolly, word flags)
{
if (flags == SCAN_PRE_ORDER)
{
const TString& leaf = *(TString*)jolly;
TString id; tree.curr_id(id);
const int slash = id.rfind('/');
if (slash > 0)
id = id.mid(slash+1);
if (id == leaf)
return TRUE;
}
return FALSE;
}
bool TMenu_tree::find_string(const TString& str)
{
TFind_string_data data;
data._str = str; data._str.upper();
data._ignore_list = &_menu->search_ignore_list();
if (data._str != _menu->last_search_string())
{
_menu->last_search_string() = data._str;
_menu->search_ignore_list().destroy();
}
goto_root();
bool ok = scan_depth_first(find_string_callback, &data, SCAN_PRE_ORDER);
if (ok)
_menu->search_ignore_list().add(curr_submenu().name());
else
_menu->search_ignore_list().destroy();
return ok;
}
bool TMenu_tree::find_leaf(const TString& str)
{
goto_root();
bool ok = scan_depth_first(find_leaf_callback, (void *)&str, SCAN_PRE_ORDER);
return ok;
}
void TMenu_tree::node2id(const TObject* node, TString& id) const
{
TString* str = (TString*)node;
id = *str;
}
bool TMenu_tree::goto_root()
{
TSubmenu* sm = _menu->find(_root_id);
if (sm)
{
_curr_id = _root_id;
_curr_id << ".0";
_submenu = sm;
_menuitem = 0;
}
return sm != NULL;
}
bool TMenu_tree::goto_firstson()
{
const TMenuitem& mi = curr_item();
if (mi.is_submenu())
{
const TSubmenu* sm = _menu->find(mi.action());
if (sm && sm->items() > 0)
{
_curr_id << '/' << mi.action() << ".0";
_submenu = sm;
_menuitem = 0;
return TRUE;
}
}
return FALSE;
}
bool TMenu_tree::goto_rbrother()
{
if (_menuitem < _submenu->items()-1)
{
const int dot = _curr_id.rfind('.');
_curr_id.cut(dot+1);
_curr_id << (++_menuitem);
return TRUE;
}
return FALSE;
}
bool TMenu_tree::goto_node(const TString &id)
{
const int dot = id.rfind('.');
CHECKS(dot > 0, "Invalid tree node ", (const char*)id);
_menuitem = atoi(id.mid(dot+1));
_curr_id = id.left(dot);
const int slash = _curr_id.rfind('/');
_curr_id = _curr_id.mid(slash+1);
_submenu = _menu->find(_curr_id);
_curr_id = id;
return _submenu != NULL;
}
bool TMenu_tree::has_son() const
{
const TMenuitem& mi = curr_item();
return mi.is_submenu();
}
bool TMenu_tree::has_rbrother() const
{
return _menuitem < _submenu->items()-1;
}
bool TMenu_tree::has_root() const
{
return _root_id.not_empty();
}
bool TMenu_tree::has_father() const
{
return _curr_id.find('/') > 0;
}
bool TMenu_tree::has_lbrother() const
{
return _menuitem > 0;
}
bool TMenu_tree::goto_father()
{
const int slash = _curr_id.rfind('/');
if (slash > 0)
{
const TString id = _curr_id.left(slash);
return goto_node(id);
}
return FALSE;
}
bool TMenu_tree::goto_lbrother()
{
if (_menuitem > 0)
{
const int dot = _curr_id.rfind('.');
_curr_id.cut(dot+1);
_curr_id << (--_menuitem);
return TRUE;
}
return FALSE;
}
TObject* TMenu_tree::curr_node() const
{
return &((TMenu_tree*)this)->_curr_id;
}
bool TMenu_tree::get_description(TString& desc) const
{
const TMenuitem& mi = curr_item();
desc = mi.caption();
return desc.not_empty();
}
TImage* TMenu_tree::image(bool selected) const
{
const TMenuitem& mi = curr_item();
if (mi.disabled())
return get_res_image(BMP_STOP);
return TTree::image(selected);
}
long TMenu_tree::find_node(const TString& id)
{
TFind_node_data data;
data._id = id;
data._count = 0;
goto_root();
scan_depth_first(find_node_callback, &data,
SCAN_PRE_ORDER | SCAN_IGNORING_UNEXPANDED);
return data._count;
}
TMenu_tree::TMenu_tree(TMenu& menu)
: _menu(&menu), _curr_id(128, '/')
{
_root_id = _menu->current().name();
goto_root();
}
///////////////////////////////////////////////////////////
// Utility
///////////////////////////////////////////////////////////
void synchronize_tree_field(TTree_field& tf)
{
TMenu_tree& mt = *(TMenu_tree*)tf.tree();
tf.select_current();
TString id; mt.curr_id(id); // Memorizza nodo corrente
mt.shrink_all();
mt.goto_node(id);
do
{
mt.expand();
}
while (mt.goto_father());
mt.goto_node(id);
tf.set_tree(&mt); // Azzera origine
TField_window& win = tf.win();
win.force_update();
}
///////////////////////////////////////////////////////////
// TMenulist_field
///////////////////////////////////////////////////////////
class TMenulist_images : public TCache
{
WINDOW _win;
protected:
TObject* key2obj(const char* key);
bool can_be_transparent(const TImage& i) const;
public:
void set_owner(WINDOW win) { _win = win; }
TImage* image(const TString& filename);
TMenulist_images() : TCache(17), _win(NULL_WIN) { }
};
bool TMenulist_images::can_be_transparent(const TImage& i) const
{
const int w = i.width()-1;
const int h = i.height()-1;
const COLOR col = i.get_pixel(0,0);
if (i.get_pixel(w,0) != col)
return FALSE;
if (i.get_pixel(w,h) != col)
return FALSE;
if (i.get_pixel(0,h) != col)
return FALSE;
return TRUE;
}
inline int fast_hypot(int x, int y)
{
// loop unrolled
#define TEST(s, h, i) { const int k = h+i; if (k*k <= s) h = k; }
const int s = x*x + y*y;
int h = 0;
TEST(s, h, 512); TEST(s, h, 256); TEST(s, h, 128);
TEST(s, h, 64); TEST(s, h, 32); TEST(s, h, 16);
TEST(s, h, 8); TEST(s, h, 4); TEST(s, h, 2); TEST(s, h, 1);
return h;
}
TObject* TMenulist_images::key2obj(const char* key)
{
TImage* img = NULL;
Patch level : 2.0 470 Files correlati : ba0.exe ba1.exe ba3.exe ba4.exe Ricompilazione Demo : [ ] Commento : EP20037 Esempio : Visualizzazione liquidazione, Indico: esercizio =2003, mese liquidazione =gennaio seleziono la ditta clicco su conferma. Nella visualizzazione la barra di scorrimento non funziona. EP20038 Inserendo nel campo "utente" un'utente inesistente e nel campo "password" ad.min , entro in campo senza che venga segnalata la non esistenza dell'utente EP20041 Col mouse seleziono un codice di pagamento già inserito e clicco sul bottone stampa.A video (come da impostazioni stampante) viene visualizzata la stampa della condizione di pagamento selezionata.Clicco su stampa, non parte la stampa su carta. Clicco su fine ritorno nella maschera "stampa condizioni di pagamento", clicco su fine errore ba3.exe EP20049 Seleziono un codice valuta inserito con spunta su voce "contro euro" in tabella valute; la spunta viene riportata anche nella maschera "Cambi giornalieri". Inserisco la data di oggi nel campo data del group box valuta e col mouse mi posizono sul campo cambio: la spunta sulla voce "contro euro" scompare EP20050 Clicco sul bottone di ricerca e richiamo una ditta memorizzata. Clicco sul bottone posta errore il campo 203 non nesiste EP20054 Ho registrato tre anagrafiche. Col mouse.Clicco sul bottone di ricerca e richiamo la n°2. Clicco sulla freccia singola a sinistra del bottone ricerca per posizionarmi sull'anagrafica n°1 e viene visualizzato messaggio vuoi registrare le modifiche?(anche per altre freccie associate al bottone) EP20055 Col mouse.Clicco su ricerca e richiamo un'anagrafica già presente.Clicco sul bottone Nuovo:messaggio registrare le modifiche? EP20057 clicco sul bottone di ricerca e seleziono un utente già registrato. I campi vengono compilati, clicco sul bottone nuovo: i campi non vengono svuotati ma compare messaggio "vuoi registrare dati inseriti?" EP20058 Ho inserito n utenti. Clicco sul bottone di ricerca e richiamo un utente già registrato. Clicco sulla freccina singola a sx del botone ricerca (e anche sulle altre freccie): messaggo "vuoi registrare dati inseriti?" EP20064 Richiamo una ditta già inserita clicco sul bottone annulla messaggio: "attività assente si desidera annullare?" EP20075 Tutte le freccie associate al bottone ricerca non funzionano git-svn-id: svn://10.65.10.50/trunk@11128 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-05-14 13:35:51 +00:00
TFilename name;
const char* ext[3] = { "jpg", "gif", "bmp" };
for (int i = 0; i < 3; i++)
{
name = key;
name << '.' << ext[i];
name.custom_path();
if (name.exist())
break;
}
if (name.exist())
{
TWait_cursor hourglass;
TImage image(name);
if (can_be_transparent(image))
image.convert_transparent_color(NORMAL_BACK_COLOR);
const int w = image.width();
const int h = image.height();
const int radius = min(w, h) / 4;
const clock_t start_timer = clock();
for (int y = h-1; y >= 0; y--)
{
for (int x = w-1; x >= 0; x--)
{
const int r = fast_hypot(x-w/2, y-h/2);
if (r > radius)
{
const double perc = 1.0 - (double(r - radius) / (radius*1.5));
if (perc >= 0.0)
{
COLOR col = image.get_pixel(x, y);
COLOR bri = blend_colors(col, NORMAL_BACK_COLOR, perc);
image.set_pixel(x, y, bri);
}
else
image.set_pixel(x, y, NORMAL_BACK_COLOR);
}
}
}
const clock_t stop_timer = clock()-start_timer;
RCT rct; xvt_vobj_get_client_rect(_win, &rct);
const double ratiox = double(rct.right) / image.width();
const double ratioy = double(rct.bottom) / image.height();
const double ratio = max(ratiox, ratioy);
const int maxx = int(ratio * image.width())-2;
const int maxy = int(ratio * image.height())-2;
img = new TImage(image, maxx, maxy);
}
return img;
}
TImage* TMenulist_images::image(const TString& filename)
{
TObject* obj = objptr(filename);
Patch level : 2.0 470 Files correlati : ba0.exe ba1.exe ba3.exe ba4.exe Ricompilazione Demo : [ ] Commento : EP20037 Esempio : Visualizzazione liquidazione, Indico: esercizio =2003, mese liquidazione =gennaio seleziono la ditta clicco su conferma. Nella visualizzazione la barra di scorrimento non funziona. EP20038 Inserendo nel campo "utente" un'utente inesistente e nel campo "password" ad.min , entro in campo senza che venga segnalata la non esistenza dell'utente EP20041 Col mouse seleziono un codice di pagamento già inserito e clicco sul bottone stampa.A video (come da impostazioni stampante) viene visualizzata la stampa della condizione di pagamento selezionata.Clicco su stampa, non parte la stampa su carta. Clicco su fine ritorno nella maschera "stampa condizioni di pagamento", clicco su fine errore ba3.exe EP20049 Seleziono un codice valuta inserito con spunta su voce "contro euro" in tabella valute; la spunta viene riportata anche nella maschera "Cambi giornalieri". Inserisco la data di oggi nel campo data del group box valuta e col mouse mi posizono sul campo cambio: la spunta sulla voce "contro euro" scompare EP20050 Clicco sul bottone di ricerca e richiamo una ditta memorizzata. Clicco sul bottone posta errore il campo 203 non nesiste EP20054 Ho registrato tre anagrafiche. Col mouse.Clicco sul bottone di ricerca e richiamo la n°2. Clicco sulla freccia singola a sinistra del bottone ricerca per posizionarmi sull'anagrafica n°1 e viene visualizzato messaggio vuoi registrare le modifiche?(anche per altre freccie associate al bottone) EP20055 Col mouse.Clicco su ricerca e richiamo un'anagrafica già presente.Clicco sul bottone Nuovo:messaggio registrare le modifiche? EP20057 clicco sul bottone di ricerca e seleziono un utente già registrato. I campi vengono compilati, clicco sul bottone nuovo: i campi non vengono svuotati ma compare messaggio "vuoi registrare dati inseriti?" EP20058 Ho inserito n utenti. Clicco sul bottone di ricerca e richiamo un utente già registrato. Clicco sulla freccina singola a sx del botone ricerca (e anche sulle altre freccie): messaggo "vuoi registrare dati inseriti?" EP20064 Richiamo una ditta già inserita clicco sul bottone annulla messaggio: "attività assente si desidera annullare?" EP20075 Tutte le freccie associate al bottone ricerca non funzionano git-svn-id: svn://10.65.10.50/trunk@11128 c028cbd2-c16b-5b4b-a496-9718f37d4682
2003-05-14 13:35:51 +00:00
if (obj == NULL && filename != "ba00")
obj = objptr("ba00");
return (TImage*)obj;
}
class TMenulist_window : public TField_window
{
enum { MENU_COLS = 3, MENU_ROWS = 5 };
private:
TMenu_tree* _tree;
TString _curr_node;
bool _can_go_back;
TMenulist_images _images;
TString _image_name;
int _selected;
TPointer_array _sorted;
protected:
virtual void update();
virtual void handler(WINDOW win, EVENT* ep);
virtual bool on_key(KEY k);
void synchronize_buddy_tree() const;
void draw_item(int i);
void click_on(int index);
void select(int s, int direction);
public:
void curr_item(TToken_string& id) const;
void set_menu(TMenu_tree& mt);
TMenulist_window(int x, int y, int dx, int dy, WINDOW parent, TMenulist_field* owner);
virtual ~TMenulist_window();
};
void TMenulist_window::draw_item(int i)
{
if (i < 0 && i >= _sorted.items())
return; // Scarta elementi non validi
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
const int width = rct.right - rct.left;
const int height = rct.bottom - rct.top;
xvt_set_font(win(), NULL, 0, 0); // Set default font
set_opaque_text(TRUE);
const TMenuitem& item = (const TMenuitem&)_sorted[i];
if (i == _selected && item.enabled())
{
set_color(item.color(), FOCUS_BACK_COLOR);
}
else
{
COLOR bc = item.enabled() ? REQUIRED_BACK_COLOR : DISABLED_BACK_COLOR;
set_color(item.color(), bc);
}
const int row = i / MENU_COLS;
const int col = i % MENU_COLS;
const int left = col * width / MENU_COLS;
const int right = (col+1) * width / MENU_COLS;
const int top = row * height / MENU_ROWS;
const int bottom = (row+1) * height / MENU_ROWS;
const int maxchars = (right-left)/CHARX - 1;
const int cx = (left+right)/2;
const int cy = (top+bottom)/2;
const int ico = item.enabled() ? item.icon() : 0;
const int ix = cx-16;
const int iy = top+2;
if (item.is_submenu())
{
xvt_dwin_draw_icon(win(), ix, iy, 10202);
if ( ico > 0)
xvt_dwin_draw_icon(win(), ix, iy+4, ico);
}
else
{
xvt_dwin_draw_icon(win(), ix, iy, ico > 0 ? ico : ICON_RSRC);
}
TString str = item.caption();
if (i == 0 && _can_go_back)
str.insert("(..)\n");
TParagraph_string para(str, maxchars);
int y = iy + 32 + CHARY-2;
FOR_EACH_TOKEN(para, line)
{
const int ll = xvt_dwin_get_text_width(win(), line, -1);
const int x = cx - ll/2;
xvt_dwin_draw_text(win(), x, y, line, -1);
y += CHARY-2;
}
if (item.disabled())
xvt_dwin_draw_icon(win(), ix+4, iy+4, 10203); // Stop icon
}
void TMenulist_window::update()
{
const bool db = _tree != NULL && ADVANCED_GRAPHICS;
TImage* img = db ? _images.image(_image_name) : NULL; // Delay time before clearing
TField_window::update();
if (_tree == NULL)
return; // Nothing to draw
if (img != NULL)
{
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
const int x = (rct.right - img->width())/2;
const int y = (rct.bottom - img->height())/2;
img->draw(win(), x, y);
}
for (int i = 0; i < _sorted.items(); i++)
draw_item(i);
}
void TMenulist_window::click_on(int index)
{
if (index >= 0 && index < _sorted.items())
{
const TMenuitem& mi = (const TMenuitem&)_sorted[index];
if (mi.enabled())
{
if (xvt_vobj_get_attr(NULL_WIN, ATTR_SPEECH_MODE) & (1<<7))
{
const TString& str = mi.caption();
if (str.find("..") < 0)
xvt_dm_post_speech(str, 7, TRUE);
}
if (mi.is_submenu())
{
if (index == 0 && _can_go_back) // S<> di un livello
{
_tree->goto_node(_curr_node);
_tree->goto_father();
set_menu(*_tree);
}
else // Gi<47> di un livello
{
if (mi.perform()) // Eventuale richiesta ditta
{
_tree->goto_node(_curr_node);
const TSubmenu& mnu = _tree->curr_submenu();
for (int i = 0; i < mnu.items(); i++)
{
const TMenuitem& ti = mnu[i];
if (ti.action() == mi.action())
{
_tree->goto_firstson();
set_menu(*_tree);
synchronize_buddy_tree();
break;
}
_tree->goto_rbrother();
}
}
}
}
else
{
mi.perform();
}
set_focus();
}
else
xvt_sys_beep(1);
}
}
void TMenulist_window::handler(WINDOW win, EVENT* ep)
{
switch (ep->type)
{
case E_MOUSE_DOWN:
{
RCT rct; xvt_vobj_get_client_rect(win, &rct);
const int row = ep->v.mouse.where.v * MENU_ROWS / rct.bottom;
const int col = ep->v.mouse.where.h * MENU_COLS / rct.right;
const index = row * MENU_COLS + col;
if (ep->v.mouse.button > 0) // Tasto destro
{
if (index < _sorted.items())
{
const TMenuitem& mi = (const TMenuitem&)_sorted[index];
message_box(mi.action());
}
else
{
if (_can_go_back)
click_on(0);
}
}
else
{
click_on(index); // Tasto sinistro
}
}
break;
default:
break;
}
TField_window::handler(win, ep);
}
void TMenulist_window::select(int s, int direction)
{
const int old_selection = _selected;
if (s < 0)
s = 0;
if (s >= _sorted.items())
s = _sorted.last();
_selected = s;
const TMenuitem& mi = (const TMenuitem&)_sorted[_selected];
if (!mi.enabled())
{
for (_selected += direction; ; _selected += direction)
{
if (_selected < 0)
_selected = _sorted.last();
if (_selected >= _sorted.items())
_selected = 0;
if (_selected == s) // Ho rifatto l'intero giro!
break;
const TMenuitem& item = (const TMenuitem&)_sorted[_selected];
if (item.enabled())
break; // Ho trovato un elemento abilitato!
}
}
draw_item(old_selection);
draw_item(_selected);
}
bool TMenulist_window::on_key(KEY k)
{
switch (k)
{
case K_ESC:
case K_BACKSPACE:
if (_tree != NULL && _can_go_back) // S<> di un livello
click_on(0);
break;
case K_ENTER:
case K_SPACE:
click_on(_selected);
break;
case K_HOME:
select(0, +1);
break;
case K_UP:
case K_PREV:
select(_selected - MENU_COLS, -1);
break;
case K_DOWN:
case K_NEXT:
select(_selected + MENU_COLS, +1);
break;
case K_LEFT:
case K_BTAB:
select(_selected-1, -1);
break;
case K_RIGHT:
case K_TAB:
select(_selected+1, +1);
break;
case K_END:
select(_sorted.last(), -1);
break;
default:
break;
}
return TRUE;
}
void TMenulist_window::synchronize_buddy_tree() const
{
TMask& m = owner().mask();
for (int i = 0; i < m.fields(); i++)
{
TMask_field& mf = m.fld(i);
if (mf.is_kind_of(CLASS_TREE_FIELD))
{
TTree_field& tf = (TTree_field&)mf;
synchronize_tree_field(tf);
break;
}
}
}
void TMenulist_window::curr_item(TToken_string& id) const
{
if (_selected >= 0 && _selected < _sorted.items())
{
const TMenuitem& item = (const TMenuitem&)_sorted[_selected];
const TSubmenu& sm = item.submenu();
const int index = sm.find(item);
id = item.caption();
id.add(sm.name());
id << '.' << index;
}
}
void TMenulist_window::set_menu(TMenu_tree& tree)
{
_tree = &tree;
tree.curr_id(_curr_node);
const int dot = _curr_node.rfind('.')+1;
int sel = -1;
if (dot > 0)
{
sel = atoi(_curr_node.mid(dot));
_curr_node.overwrite("0", dot);
}
_sorted.destroy();
_can_go_back = tree.goto_father();
if (_can_go_back)
{
_sorted.add(tree.curr_item());
tree.goto_node(_curr_node);
}
int folders = _sorted.items();
// Lista riordinata dei menu items
const TSubmenu& mnu = tree.curr_submenu();
for (int i = 0; i < mnu.items(); i++)
{
const TMenuitem& item = mnu[i];
if (item.is_submenu())
_sorted.insert(item, folders++);
else
_sorted.add(item);
}
TString80 sel_act;
if (sel >= 0 && sel < mnu.items())
sel_act= mnu[sel].action();
for (_selected = _sorted.last(); _selected > 0; _selected--)
{
const TMenuitem& sm = (const TMenuitem&)_sorted[_selected];
if (sm.enabled() && sm.action() == sel_act)
break;
}
_image_name = mnu.picture();
force_update();
}
TMenulist_window::TMenulist_window(int x, int y, int dx, int dy, WINDOW parent, TMenulist_field* owner)
: TField_window(x, y, dx, dy, parent, owner), _tree(NULL)
{
set_scroll_max(0, 0); // Get rid of that useless scrollbars
_images.set_owner(win());
}
TMenulist_window::~TMenulist_window()
{
}
TField_window* TMenulist_field::create_window(int x, int y, int dx, int dy, WINDOW parent)
{
return new TMenulist_window(x, y, dx, dy, parent, this);
}
void TMenulist_field::create(short dlg, int x, int y, int dx, int dy)
{
_dlg = dlg;
_win = create_window(x, y, dx, dy, mask().win());
}
void TMenulist_field::set_menu(TMenu_tree& mt)
{
TMenulist_window& w = (TMenulist_window&)win();
w.set_menu(mt);
}
void TMenulist_field::curr_item(TToken_string& id) const
{
TMenulist_window& w = (TMenulist_window&)win();
w.curr_item(id);
}