#include #include #include "../ve/ve0100.h" #include "../ve/veini.h" #include "../ve/veuml.h" #include "../ve/veuml3.h" #include "../ve/verig.h" #include "../ve/vepriv.h" #include "../ve/velib.h" #include "../ve/velib04.h" #define F_K F_USERFLD #define F_LIVELLO F_USERFLD+1 #define F_DETTAGLIO F_USERFLD+2 #define F_COPIA F_USERFLD+3 #define F_INCOLLA F_USERFLD+4 #define F_SHRINK_ALL F_USERFLD+5 #define F_ZOOM_ALL F_USERFLD+6 #define F_SHRINK_ROW F_USERFLD+7 #define F_ZOOM_ROW F_USERFLD+8 #define FOR_EACH_DOC_ROW_BACK(d, r, row) const TRiga_documento* row = NULL; for (int r = d.rows(); r > 0 && (row = &d[r]) != NULL; r--) ////////////////////////////////////////// //// CLASSE TGestione_preventivo_msk //// ////////////////////////////////////////// //Definizione della classe della maschera class TGestione_preventivo_msk : public TDocumento_mask { int _rule; int _clipboard_row; protected: //hanlder di documento: static bool pe_data_handler(TMask_field& f, KEY k); //handler di riga: static bool pe_ritirato_handler(TMask_field& f, KEY k); static bool pe_codart_handler(TMask_field& f, KEY k); static bool pe_qta_handler(TMask_field& f, KEY k); static bool ss_notify(TSheet_field& ss, int r, KEY key); virtual void on_idle(); virtual void highlight_row(int row, COLOR back = COLOR_INVALID, COLOR fore = COLOR_INVALID, bool dirty = true, bool update = true); const TString & build_tree_string(int level); public: static bool pe_espandi_handler(TMask_field& f, KEY k); static bool pe_espandi_riga_handler(TMask_field& f, KEY k); static bool pe_copia_handler(TMask_field& f, KEY k); static bool pe_incolla_handler(TMask_field& f, KEY k); virtual void user_set_handler( short fieldid, int index); virtual void user_set_row_handler(TMask& rm, short field, int index); virtual TVariable_mask * riga_mask(int numriga); virtual void doc2mask(bool reload_clifo = true, bool force_load = false, bool update = true); TGestione_preventivo_msk(const char* tipodoc); }; ////////////////////////////////////////// //// CLASSE TGestione_preventivo_APP //// ////////////////////////////////////////// // Definizione della classe dell'applicazione motore class TGestione_preventivo_app : public TMotore_application { protected: virtual TMask* get_mask( int mode ); virtual int write( const TMask& m ); virtual int rewrite( const TMask& m ); virtual int read ( TMask& m ); virtual void init_insert_mode( TMask& m ); void elimina_vuote( const TMask& m); public: TGestione_preventivo_app() {} }; inline TGestione_preventivo_app& peapp() { return (TGestione_preventivo_app &)main_app(); }; ////////////////////////////////////////// //// CLASSE TGestione_preventivo_MSK //// ////////////////////////////////////////// const TString & TGestione_preventivo_msk::build_tree_string(int level) { TString & tree = get_tmp_string(20); if (level < 10) { if (level > 0) tree.fill(' ', level); tree << '+'; tree.rpad(10, '-'); } else tree = " +"; return tree; } //////////////////////////// // HANDLER DI DOCUMENTO // //////////////////////////// void TGestione_preventivo_msk:: on_idle() { TDocumento_mask::on_idle(); } //magico metodo per settare, al cambio riga dello sheet, il focus sul campo desiderato (il campo in questione è.. //..definito nella on_idle(); ricordarsi la set_notify() nel costruttore della maschera senno' viene eseguito l'ss_notify().. //..standard e non questo qui ridefinito. Allah! bool TGestione_preventivo_msk::ss_notify(TSheet_field& ss, int r, KEY key) { TGestione_preventivo_msk& mask = (TGestione_preventivo_msk&) ss.mask(); TSheet_field & sh = mask.sfield(F_SHEET); TDocumento& doc = mask.doc(); switch (key) { case K_TAB: // entrata { TRiga_documento& row = doc[r + 1]; TMask & row_mask = sh.sheet_row_mask(r); const int level = row.get_int(RDOC_LEVEL); const bool prodfin = level == 0; const bool price_enabled = (r + 1 == doc.physical_rows()) || (level >= doc[r + 2].get_int(RDOC_LEVEL)); short id; row_mask.enable(FR_PREZZO, price_enabled); row_mask.enable(FR_JOLLY2, price_enabled); for (id = FR_CDC1; id < FR_CDC12; id++) row_mask.enable(id, prodfin); for (id = FR_DESCDC1; id < FR_DESCDC12; id++) row_mask.enable(id, prodfin); } break; case K_CTRL + K_INS: // Inserimento { const int doc_row = r + 1; int level = 0; TRiga_documento & row = doc[doc_row]; if (r > 0 && row.is_merce()) { const int father_sheet_row = r - 1; TRiga_documento& father_row = doc[father_sheet_row + 1]; const int rows = doc.physical_rows(); level = father_row.get_int(RDOC_LEVEL); const int next_level = mask.get_int(F_LIVELLO); if ( next_level > 0 && (doc_row == rows || level > doc[doc_row + 1].get_int(RDOC_LEVEL))) level = (doc_row == rows || next_level - 1 >= doc[doc_row + 1].get_int(RDOC_LEVEL)) ? next_level - 1 : doc[doc_row + 1].get_int(RDOC_LEVEL); else if (mask.get_bool(F_DETTAGLIO) || (doc_row < rows && level < doc[doc_row + 1].get_int(RDOC_LEVEL))) level++; if (level > 0) { row.put(RDOC_CODCOSTO, father_row.get(RDOC_CODCOSTO)); row.put(RDOC_CODCMS, father_row.get(RDOC_CODCMS)); row.put(RDOC_FASCMS, father_row.get(RDOC_FASCMS)); short id; sh.disable_cell(father_sheet_row, sh.cid2index(FR_PREZZO)); sh.disable_cell(father_sheet_row, sh.cid2index(FR_JOLLY2)); father_row.zero(RDOC_PREZZO); father_row.zero(RDOC_K); father_row.autoload(sh); sh.force_update(father_sheet_row); for (id = FR_CDC1; id < FR_CDC12; id++) sh.disable_cell(r, sh.cid2index(id)); } } row.put(RDOC_LEVEL, level); row.put(RDOC_TREE, mask.build_tree_string(level)); row.autoload(sh); mask.reset(F_LIVELLO); mask.reset(F_DETTAGLIO); } break; case K_DEL: // Cancellazione { const int doc_row = r + 1; const int rows = doc.physical_rows(); if (doc_row < rows) { TRiga_documento & row = doc[doc_row]; const int level = row.get_int(RDOC_LEVEL); int i; int last_row = doc_row; for (i = doc_row + 1; i <= rows; i++) if (level < doc[i].get_int(RDOC_LEVEL)) last_row = i; else break; for (i = last_row; i > doc_row; i--) { doc.destroy_row(i, true); sh.destroy(i - 1); } sh.force_update(); } } break; default: break; } return TDocumento_mask::ss_notify(ss, r, key); } void TGestione_preventivo_msk::highlight_row(int row, COLOR back, COLOR fore, bool dirty, bool update) { TDocumento_mask::highlight_row(row, back, fore, dirty, false); TRiga_documento& rigadoc = doc()[row + 1]; TSheet_field& sf = sfield(F_SHEET); COLOR back1 = back, back2 = COLOR_BLUE; const TColor_rule * c = (TColor_rule *) color_rules().objptr(_rule); if (c != NULL) c->colors(back2, fore); back = blend_colors(back1, back2, 1.0 - (((double) rigadoc.get_int(RDOC_LEVEL)) / 10.0)); sf.set_back_and_fore_color(back, fore, row); if (update) sf.force_update(row); } TVariable_mask * TGestione_preventivo_msk::riga_mask(int numriga) { const bool is_new = new_mask(numriga); TVariable_mask* m = TDocumento_mask::riga_mask(numriga); if (is_new && m != NULL) { const TRiga_documento& riga = doc()[numriga + 1]; TEdit_field & tree = m->add_string(FR_JOLLY1, 0, "Albero ", 2, 20, 10, "D_"); TEdit_field & k = m->add_string(FR_JOLLY2, 0, "K ", 25, 20, 25); m->set_handler(FR_CODART, pe_codart_handler); m->set_handler(FR_QTA, pe_qta_handler); tree.set_field(RDOC_TREE); k.set_field(RDOC_K); } return m; } void TGestione_preventivo_msk::doc2mask(bool reload_clifo, bool force_load, bool update) { TDocumento_mask::doc2mask(reload_clifo, force_load, false); TSheet_field& s = sfield(F_SHEET); const int righe = s.items(); const TDocumento & d = doc(); for (int i = 0; i < righe; i++) { const TRiga_documento & row = d[i + 1]; const int level = row.get_int(RDOC_LEVEL); const bool prodfin = level == 0; const bool price_enabled = (i + 1 == d.physical_rows()) || (level >= d[i + 2].get_int(RDOC_LEVEL)); s.enable_cell(i, s.cid2index(FR_PREZZO), price_enabled); s.enable_cell(i, s.cid2index(FR_JOLLY2), price_enabled); for (short id = FR_CDC1; id < FR_CDC12; id++) s.enable_cell(i, s.cid2index(id), prodfin); } //aggiorna i colori delle righe e forza l'update dello sheet highlight(); } //PE_TESTATA_HANDLER: handler che si occupa di decodificare i campi data in testata bool TGestione_preventivo_msk::pe_data_handler(TMask_field& f, KEY k) { bool ok = true; TGestione_preventivo_msk& mask = (TGestione_preventivo_msk&)f.mask(); return ok; } bool TGestione_preventivo_msk::pe_espandi_handler(TMask_field& f, KEY k) { if (k == K_SPACE) { TGestione_preventivo_msk& mask = (TGestione_preventivo_msk&)f.mask(); TSheet_field& sh = mask.sfield(F_SHEET); const int r = sh.selected(); const int size = f.dlg() == F_SHRINK_ALL ? 1 : -1; int row_to_select = 0; FOR_EACH_SHEET_ROW(sh, i, row) { const int row_level = mask.doc()[i + 1].get_int(RDOC_LEVEL); if (row_level > 0) sh.set_row_height(i, size); else if (i <= r) row_to_select = i; } if (size < 0) sh.select(row_to_select); sh.force_update(); } return true; } bool TGestione_preventivo_msk::pe_espandi_riga_handler(TMask_field& f, KEY k) { if (k == K_SPACE) { TGestione_preventivo_msk& mask = (TGestione_preventivo_msk&)f.mask(); TSheet_field& sh = mask.sfield(F_SHEET); const int r = sh.selected(); const int level = mask.doc()[r + 1].get_int(RDOC_LEVEL); if (r >= 0 && r < sh.items()) { const int size = f.dlg() == F_SHRINK_ROW ? 1 : -1; for (int i = r + 1; i < sh.items(); i++) { const int child_level = mask.doc()[i + 1].get_int(RDOC_LEVEL); if (child_level > level) sh.set_row_height(i, size); else break; } } sh.force_update(); } return true; } bool TGestione_preventivo_msk::pe_copia_handler(TMask_field& f, KEY k) { bool ok = true; if (k == K_SPACE) { TGestione_preventivo_msk& mask = (TGestione_preventivo_msk&)f.mask(); mask._clipboard_row = mask.sfield(F_SHEET).selected() + 1; } return ok; } bool TGestione_preventivo_msk::pe_incolla_handler(TMask_field& f, KEY k) { bool ok = true; if (k == K_SPACE) { TGestione_preventivo_msk& mask = (TGestione_preventivo_msk&)f.mask(); if (mask._clipboard_row > 0) { TDocumento & doc = mask.doc(); TSheet_field & sh = mask.sfield(F_SHEET); const int selected_row = sh.selected() + 1; const int rows = doc.physical_rows(); const int next_level = mask.get_int(F_LIVELLO); const int orig_level = doc[mask._clipboard_row].get_int(RDOC_LEVEL); const int level = next_level > 0 ? next_level - 1 : orig_level; const int level_offset = level - orig_level; int i; int start_row = -1; for (i = selected_row; start_row < 0 && i <= rows; i++) { const int row_level = doc[i].get_int(RDOC_LEVEL); if (level == row_level) start_row = i; } if (start_row > 0) { const bool shift_source_rows = start_row <= mask._clipboard_row; for (i = mask._clipboard_row; i <= doc.physical_rows(); i++) { int row_level = doc[i].get_int(RDOC_LEVEL); if (i > mask._clipboard_row && orig_level >= row_level) break; const TRiga_documento & row = doc[i]; sh.insert(start_row - 1, false, true); TRiga_documento & new_row = doc[start_row]; doc.copy_data(new_row, row); row_level += level_offset; new_row.put(RDOC_LEVEL, row_level); new_row.put(RDOC_TREE, mask.build_tree_string(level)); new_row.autoload(sh); start_row++; if (shift_source_rows) i++; } mask.highlight(); sh.force_update(); } mask._clipboard_row = -1; mask.reset(F_LIVELLO); } } return ok; } /////////////////////// // HANDLER DI RIGA // /////////////////////// bool TGestione_preventivo_msk::pe_codart_handler(TMask_field& f, KEY k) { TMask& row_mask = f.mask(); bool ok = codart_handler( f, k ); TSheet_field * sh = row_mask.get_sheet(); if (ok && sh != NULL && k == K_TAB && f.focusdirty()) { TDocumento_mask & mask = (TDocumento_mask &) sh->mask(); TDocumento & doc = mask.doc(); bool update = false; const int r = sh->selected(); TRiga_documento & row = doc[r + 1]; if (row_mask.field(FR_JOLLY2).active()) { const TString& codart = row.get(RDOC_CODARTMAG); if (codart.full()) { const TArticolo_giacenza & art = cached_article(codart); TString80 k = art.get(ANAMAG_PERCRIC); if (k.blank()) { const TString catmer = art.get(ANAMAG_GRMERC); k = cache().get("GMC", catmer, "S2"); if (k.blank()) k = cache().get("GMC", catmer.left(3), "S2"); } if (k.full()) row_mask.set(FR_JOLLY2, k); } } if (!row_mask.field(FR_PREZZO).active()) row_mask.set(FR_PREZZO, ""); } if (k == K_F8) { TSheet_field * sh = row_mask.get_sheet(); if (sh != NULL) { TGestione_preventivo_msk & mask = (TGestione_preventivo_msk &) sh->mask(); TDocumento & doc = mask.doc(); const int rows = doc.physical_rows(); for (int i = 1; i <= rows; i++) { TRiga_documento & row = doc[i]; const int level = row.get_int(RDOC_LEVEL); const bool prodfin = level == 0; const bool price_enabled = (i == doc.physical_rows()) || (level >= doc[i + 1].get_int(RDOC_LEVEL)); short id; sh->enable_cell(i - 1, sh->cid2index(FR_PREZZO), price_enabled); sh->enable_cell(i - 1, sh->cid2index(FR_JOLLY2), price_enabled); for (id = FR_CDC1; id < FR_CDC12; id++) sh->enable_cell(i - 1, id, prodfin); for (id = FR_DESCDC1; id < FR_DESCDC12; id++) sh->enable_cell(i - 1, id, prodfin); if (row.get(RDOC_TREE).blank()) { row.put(RDOC_TREE, mask.build_tree_string(level)); row.autoload(*sh); mask.highlight_row(i -1, COLOR_INVALID, COLOR_INVALID, true, false); } } sh->force_update(); } } return ok; } bool TGestione_preventivo_msk::pe_qta_handler(TMask_field& f, KEY k) { bool ok = qta_handler( f, k ); if (ok) { TMask& row_mask = f.mask(); TSheet_field * sh = row_mask.get_sheet(); if (sh != NULL) { TDocumento_mask & mask = (TDocumento_mask &) sh->mask(); TDocumento & doc = mask.doc(); if (k == K_F8) { const int r = sh->selected(); if (r > 0) { TRiga_documento & row = doc[r + 1]; const int level = row.get_int(RDOC_LEVEL); if (level > 0) { int father_row = r; while (r > 1 && level == doc[father_row].get_int(RDOC_LEVEL)) father_row--; TRiga_documento & row = doc[father_row]; const real qta_prec = row.get_real(RDOC_QTA); real qta(f.get()); TToken_string & shrow = sh->row(r); qta *= qta_prec; shrow.add(qta.string(), sh->cid2index(FR_QTA)); sh->force_update(r); row.put(RDOC_QTA, qta); f.focusdirty(); } } } if (f.to_check(k, true)) { const int r = sh->selected(); TRiga_documento & row = doc[r + 1]; const real old_qta = row.get_real(RDOC_QTA); const real qta = row_mask.get_real(FR_QTA); const int level = row.get_int(RDOC_LEVEL); if (old_qta != qta) { const int rows = doc.physical_rows(); for (int i = r + 2; i <= rows && level < doc[i].get_int(RDOC_LEVEL); i++) { TToken_string & shrow = sh->row(i - 1); real row_qta(shrow.get(sh->cid2index(FR_QTA))); row_qta *= qta; if (!old_qta.is_zero()) row_qta /= old_qta; row_qta.round(5); shrow.add(row_qta.string(), sh->cid2index(FR_QTA)); doc[i].put(RDOC_QTA, row_qta); } row.put(RDOC_QTA, qta); sh->force_update(); } } } } return ok; } //metodo che setta gli handler sui campi di riga void TGestione_preventivo_msk::user_set_row_handler(TMask& rm, short field, int index) { switch(index) { case 5101: rm.set_handler(field, pe_codart_handler); break; case 5102: rm.set_handler(field, pe_qta_handler); break; default : TDocumento_mask::user_set_row_handler(rm, field, index); break; } } //metodo che setta l'handler di bolla void TGestione_preventivo_msk::user_set_handler( short fieldid, int index) { switch(index) { case 5101: set_field_handler(fieldid, pe_data_handler); break; default : TDocumento_mask::user_set_handler(fieldid, index); break; } } TGestione_preventivo_msk::TGestione_preventivo_msk(const char* tipodoc) : TDocumento_mask(tipodoc), _clipboard_row(-1) { TConfig* configpe = new TConfig(CONFIG_DITTA, "pe"); sfield(F_SHEET).set_notify( ss_notify ); _rule = color_rules().add(new TColor_rule("Livello", "", _numexpr, COLOR_BLUE, FOCUS_COLOR)); } ////////////////////////////////////////// //// CLASSE TGESTIONE_PREVENTIVO_APP //// ////////////////////////////////////////// //ridefinisco il metodo get_mask delle TMotore_application TMask* TGestione_preventivo_app::get_mask( int mode ) { if (mode == MODE_INS || mode == MODE_MOD) { TString4 tipodoc; if (mode == MODE_MOD) tipodoc = get_relation()->curr().get(DOC_TIPODOC); // Lo prendo dalla relazione (Gelai) else tipodoc = TMotore_application::get_mask(MODE_QUERY)->get(F_TIPODOC); if (_doc_masks.objptr(tipodoc) == NULL) { TGestione_preventivo_msk* m = new TGestione_preventivo_msk(tipodoc); _doc_masks.add(tipodoc, m); const TTipo_documento& tdoc = m->doc().tipo(); const TString_array& handlers = tdoc.handlers(); FOR_EACH_ARRAY_ROW(handlers, i, row) { m->user_set_handler( row->get_int( 0 ), row->get_int( 1 ) ); } TSheet_field & sh = m->sfield(F_SHEET); const int y = m->sh_y() - 1; m->add_button(F_SHRINK_ALL, sh.page(), "--", 61, y - 1, 1, 1, "", BMP_DARROWU); m->set_handler(F_SHRINK_ALL, TGestione_preventivo_msk::pe_espandi_handler); m->add_button(F_ZOOM_ALL, sh.page(), "++", 66, y -1, 1, 1, "", BMP_DARROWD); m->set_handler(F_ZOOM_ALL, TGestione_preventivo_msk::pe_espandi_handler); m->add_button(F_SHRINK_ROW, sh.page(), "-", 71, y - 1, 1, 1, "", BMP_SARROWU); m->set_handler(F_SHRINK_ROW, TGestione_preventivo_msk::pe_espandi_riga_handler); m->add_button(F_ZOOM_ROW, sh.page(), "+", 76, y -1, 1, 1, "", BMP_SARROWD); m->set_handler(F_ZOOM_ROW, TGestione_preventivo_msk::pe_espandi_riga_handler); TEdit_field & k = m->add_string(F_K, sh.page(), "K ", 2, y, 25); k.set_field(DOC_K); m->add_number(F_LIVELLO, sh.page(), "Livello Successivo ", 33, y, 1); m->add_boolean(F_DETTAGLIO, sh.page(), "Dettaglia ", 58, y); m->add_button(F_COPIA, sh.page(), "~Copia", 71, y, 1, 1, "", BMP_COPY); m->set_handler(F_COPIA, TGestione_preventivo_msk::pe_copia_handler); m->add_button(F_INCOLLA, sh.page(), "~Incolla", 76, y, 1, 1, "", BMP_PASTE); m->set_handler(F_INCOLLA, TGestione_preventivo_msk::pe_incolla_handler); sh.enable_column(sh.cid2index(FR_JOLLY1), false); } } return TMotore_application::get_mask(mode); } //ridefinisco il metodo write delle TMotore_application int TGestione_preventivo_app::write( const TMask& m ) { TDocumento& doc = ((TDocumento_mask&) m).doc(); const TString k = doc.get(DOC_K); int max_level = 0; const int rows = doc.physical_rows(); for (int r = 1; r <= rows; r++) { const int level = doc[r].get_int(RDOC_LEVEL); if (max_level < level) max_level = level; } for (int i = 1 ; i <= rows; i++) if (doc[i].get_int(RDOC_LEVEL) == max_level && doc[i].get(RDOC_K).blank()) doc[i].put(RDOC_K, k); return TMotore_application::write(m); } //ridefinisco il metodo rewrite delle TMotore_application int TGestione_preventivo_app::rewrite( const TMask& m ) { TDocumento& doc = ((TDocumento_mask&) m).doc(); const TString k = doc.get(DOC_K); int max_level = 0; const int rows = doc.physical_rows(); for (int r = 1; r <= rows; r++) { const int level = doc[r].get_int(RDOC_LEVEL); if (max_level < level) max_level = level; } for (int i = 1 ; i <= rows; i++) if (doc[i].get_int(RDOC_LEVEL) == max_level && doc[i].get(RDOC_K).blank()) doc[i].put(RDOC_K, k); return TMotore_application::rewrite(m); } //ridefinisco il metodo read della TMotore_application int TGestione_preventivo_app::read(TMask& m) { const int err = TMotore_application::read(m); if (err == NOERR) { TDocumento_mask& mask = (TDocumento_mask&) m; TDocumento& doc = mask.doc(); const TString k = doc.get(DOC_K); for (int i = 1 ; i <= doc.physical_rows(); i++) if (k == doc[i].get(RDOC_K)) doc[i].zero(RDOC_K); } return err; } //ridefinisco il metodo init_insert_mode della TMotore_application void TGestione_preventivo_app::init_insert_mode(TMask &m) { TGestione_preventivo_msk & mask = (TGestione_preventivo_msk&) m; TDocumento& d = mask.doc(); return TMotore_application::init_insert_mode(m); } int pe0400( int argc, char* argv[]) { TGestione_preventivo_app a; a.run( argc, argv, TR("Gestione Preventivi")); return 0; }