plugin_arg_form.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:30k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: plugin_arg_form.cpp,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 21:17:08  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.1
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: plugin_arg_form.cpp,v 1000.0 2004/06/01 21:17:08 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Mike DiCuccio
  35.  *
  36.  * File Description:
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include "plugin_arg_form.hpp"
  41. #include "obj_browser.hpp"
  42. #include "obj_menu.hpp"
  43. #include <FL/Fl_Group.H>
  44. #include <FL/Fl_Int_Input.H>
  45. #include <FL/Fl_File_Input.H>
  46. #include <FL/Fl_Secret_Input.H>
  47. #include <FL/Fl_Float_Input.H>
  48. #include <FL/Fl_Multiline_Input.H>
  49. #include <FL/Fl_Box.H>
  50. #include <FL/Fl_File_Chooser.H>
  51. #include <gui/plugin/PluginValue.hpp>
  52. #include <gui/plugin/PluginValueConstraint.hpp>
  53. #include <gui/dialogs/file_browser.hpp>
  54. #include <gui/core/doc_manager.hpp>
  55. BEGIN_NCBI_SCOPE
  56. USING_SCOPE(objects);
  57. //
  58. //
  59. // formatter specializations
  60. //
  61. //
  62. //
  63. // format an input box as a built-in argument type
  64. //
  65. class CSimpleFormatter : public CArgFormatter
  66. {
  67. public:
  68.     enum EEditType {
  69.         eMultiLine,
  70.         eSingleLine,
  71.         eInteger,
  72.         eFloat,
  73.         eFile,
  74.         eSecret
  75.     };
  76.     CSimpleFormatter(objects::CPluginArg& arg);
  77.     void Process(void);
  78.     Fl_Widget* GetWidget();
  79. private:
  80.     // the group that holds everything
  81.     Fl_Group* m_Group;
  82.     // our input box
  83.     Fl_Input*   m_Input;
  84.     // the argument we represent
  85.     CRef<objects::CPluginArg> m_Arg;
  86.     static void cb_FileOpen(Fl_Widget* w, void* data);
  87. };
  88. //
  89. // format a multiline input box as a built-in argument type
  90. // this is valid only for arguments of type list
  91. //
  92. class CMultiLineFormatter : public CArgFormatter
  93. {
  94. public:
  95.     CMultiLineFormatter(objects::CPluginArg& arg);
  96.     void Process(void);
  97.     Fl_Widget* GetWidget();
  98. private:
  99.     // the group that holds everything
  100.     Fl_Group* m_Group;
  101.     // our input box
  102.     Fl_Input* m_Input;
  103.     // the argument we represent
  104.     CRef<objects::CPluginArg> m_Arg;
  105. };
  106. //
  107. // format a drop-down list as a built-in argument type
  108. //
  109. class CMenuFormatter : public CArgFormatter
  110. {
  111. public:
  112.     CMenuFormatter(objects::CPluginArg& arg);
  113.     void Process(void);
  114.     Fl_Widget* GetWidget();
  115. private:
  116.     // the group that holds everything
  117.     Fl_Group* m_Group;
  118.     // our choice
  119.     Fl_Choice*  m_Choice;
  120.     // the argument we represent
  121.     CRef<objects::CPluginArg> m_Arg;
  122. };
  123. //
  124. // format a button as a built-in argument type for
  125. //  boolean/flag arguments only.
  126. //
  127. class CButtonFormatter : public CArgFormatter
  128. {
  129. public:
  130.     CButtonFormatter(objects::CPluginArg& arg);
  131.     void Process(void);
  132.     Fl_Widget* GetWidget();
  133. private:
  134.     // the group that holds everything
  135.     Fl_Button*  m_Button;
  136.     CRef<objects::CPluginArg> m_Arg;
  137. };
  138. //
  139. // format a drop-down list as an object
  140. //
  141. class CSingleObjFormatter : public CArgFormatter
  142. {
  143. public:
  144.     CSingleObjFormatter(objects::CPluginArg& arg,
  145.                         const TConstScopedObjects& objs);
  146.     void Process(void);
  147.     Fl_Widget* GetWidget();
  148. private:
  149.     Fl_Group* m_Group;
  150.     CObjChoice* m_Choice;
  151.     TConstScopedObjects m_Objects;
  152.     CRef<objects::CPluginArg> m_Arg;
  153. };
  154. //
  155. // format a multiline browser as an array of objects
  156. //
  157. class CMultiObjFormatter : public CArgFormatter
  158. {
  159. public:
  160.     CMultiObjFormatter(objects::CPluginArg& arg,
  161.                        const TConstScopedObjects& objs);
  162.     ~CMultiObjFormatter();
  163.     void Process(void);
  164.     Fl_Widget* GetWidget();
  165. private:
  166.     void x_InitArgUserDataList();
  167.     Fl_Group*    m_Group;
  168.     CObjBrowser* m_Browser;
  169.     TConstScopedObjects m_Objects;
  170.     CRef<objects::CPluginArg> m_Arg;
  171. };
  172. //
  173. // specialized formatter for dealing with flags
  174. // this is made public because these are a special case
  175. //
  176. class CFlagPanel : public CArgFormatter
  177. {
  178. public:
  179.     CFlagPanel(objects::CPluginArgSet::Tdata& args);
  180.     void Process();
  181.     Fl_Widget* GetWidget();
  182. private:
  183.     // internal flag formatters
  184.     list< CRef<CArgFormatter> > m_Formatters;
  185.     // the group that holds everything
  186.     Fl_Group* m_Group;
  187. };
  188. // silly title widget
  189. class CPluginArgFormTitle : public Fl_Box
  190. {
  191. public:
  192.     CPluginArgFormTitle(int x, int y, int w, int h, const char* label_str = NULL)
  193.         : Fl_Box(x, y, w, h)
  194.     {
  195.         if (label_str) {
  196.             m_Title = label_str;
  197.         }
  198.         label(m_Title.c_str());
  199.         box(FL_THIN_DOWN_BOX);
  200.         color(fl_rgb_color(160, 160, 240));
  201.         align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT);
  202.     }
  203.     void SetTitle(const string& title)
  204.     {
  205.         m_Title = title;
  206.     }
  207. private:
  208.     string m_Title;
  209.     Fl_Box* m_LabelBox;
  210.     Fl_Group* m_LabelSpacer;
  211. };
  212. ////////////////////////////////////////////////////////////////////////
  213. //
  214. // CPluginArgForm
  215. //
  216. CPluginArgForm::CPluginArgForm(int x, int y, int w, int h, const char* label)
  217.     : CFlForm(x, y, w, h, label)
  218. {
  219. }
  220. // set the arguments for this form
  221. void CPluginArgForm::SetArgs(objects::CPluginArgSet& args,
  222.                              const TConstScopedObjects& selections)
  223. {
  224.     // clear the pack that holds our information
  225.     Clear();
  226.     CPluginArgSet::Tdata required;
  227.     CPluginArgSet::Tdata optional;
  228.     CPluginArgSet::Tdata flags;
  229.     // first, sort through our arguments and divide into required and optional
  230.     // pools
  231.     NON_CONST_ITERATE (CPluginArgSet::Tdata, iter, args.Set()) {
  232.         CRef<CPluginArg> arg = *iter;
  233.         if ( arg->IsSetHidden()  &&  arg->GetHidden() ) {
  234.             continue;
  235.         }
  236.         if (arg->GetType() == CPluginArg::eBoolean) {
  237.             flags.push_back(arg);
  238.         } else if (arg->GetOptional()) {
  239.             optional.push_back(arg);
  240.         } else {
  241.             required.push_back(arg);
  242.         }
  243.     }
  244.     // Create conversion cache. Might be needed for Object arguments
  245.     CRef<CConvertCache> convert_cache(new CConvertCache);
  246.     // required arguments first
  247.     if ( !required.empty() ) {
  248.         x_AddOptions(required, "Required Fields", *convert_cache, selections);
  249.     }
  250.     // flags next
  251.     if ( !flags.empty() ) {
  252.         x_AddFlags(flags, "Flags", *convert_cache);
  253.     }
  254.     // optional arguments next
  255.     if ( !optional.empty()) {
  256.         x_AddOptions(optional, "Optional Fields", *convert_cache, selections);
  257.     }
  258. }
  259. void CPluginArgForm::x_AddFlags(CPluginArgSet::Tdata& opts,
  260.                                   const char* title, 
  261.                                   CConvertCache& convert_cache)
  262. {
  263.     if (title  &&  *title) {
  264.         AddTitle(title);
  265.     }
  266.     CRef<CArgFormatter> flag_panel(new CFlagPanel(opts));
  267.     if (flag_panel) {
  268.         AddFormatter(*flag_panel);
  269.     }
  270. }
  271. void CPluginArgForm::x_AddOptions(CPluginArgSet::Tdata& opts,
  272.                                   const char* title, 
  273.                                   CConvertCache& convert_cache,
  274.                                   const TConstScopedObjects& selections)
  275. {
  276.     if (title  &&  *title) {
  277.         AddTitle(title);
  278.     }
  279.     NON_CONST_ITERATE (CPluginArgSet::Tdata, iter, opts) {
  280.         CPluginArg& arg = **iter;
  281.         CRef<CArgFormatter> fmt
  282.             (CPluginArgForm::GetFormatter(arg, selections));
  283.         if (fmt) {
  284.             AddFormatter(*fmt);
  285.         }
  286.     }
  287. }
  288. void CPluginArgForm::AddTitle(const string& title)
  289. {
  290.     CPluginArgFormTitle* widget = new CPluginArgFormTitle(0, 0, w(), 20);
  291.     widget->SetTitle(title);
  292.     AddWidget(widget);
  293. }
  294. void CPluginArgForm::AddFormatter(CArgFormatter& fmt)
  295. {
  296.     m_Formatters.push_back(CRef<CArgFormatter>(&fmt));
  297.     Fl_Widget* w = fmt.GetWidget();
  298.     if (w) {
  299.         AddWidget(w);
  300.     }
  301. }
  302. void CPluginArgForm::Process()
  303. {
  304.     NON_CONST_ITERATE (TArgFormatters, iter, m_Formatters) {
  305.         (*iter)->Process();
  306.     }
  307. }
  308. // generate a new argument formatter based on a given argument.
  309. CArgFormatter* CPluginArgForm::GetFormatter(CPluginArg& arg,
  310.                                             const TConstScopedObjects& objs)
  311. {
  312.     if (arg.GetData().IsSingle()) {
  313.         switch (arg.GetType()) {
  314.         case CPluginArg::eString:
  315.         case CPluginArg::eInteger:
  316.         case CPluginArg::eDouble:
  317.         case CPluginArg::eFile:
  318.             if (arg.IsSetConstraint()  &&
  319.                 arg.GetConstraint().front()->Which() ==
  320.                 CPluginValueConstraint::e_Set) {
  321.                 return new CMenuFormatter(arg);
  322.             } else {
  323.                 return new CSimpleFormatter(arg);
  324.             }
  325.         case CPluginArg::eBoolean:
  326.             return new CButtonFormatter(arg);
  327.         case CPluginArg::eDocument:
  328.         case CPluginArg::eObject:
  329.             return new CSingleObjFormatter(arg, objs);
  330.         default:
  331.             LOG_POST(Error << "unhandled argument type: " << (int)arg.GetType());
  332.             break;
  333.         }
  334.     } else {
  335.         switch (arg.GetType()) {
  336.         case CPluginArg::eString:
  337.         case CPluginArg::eInteger:
  338.         case CPluginArg::eDouble:
  339.             return new CMultiLineFormatter(arg);
  340.         case CPluginArg::eDocument:
  341.         case CPluginArg::eObject:
  342.             return new CMultiObjFormatter(arg, objs);
  343.         default:
  344.             LOG_POST(Error << "unhandled argument type: " << (int)arg.GetType());
  345.             break;
  346.         }
  347.     }
  348.     return NULL;
  349. }
  350. //
  351. //
  352. // internal implementation
  353. //
  354. //
  355. //
  356. // constants controlling layout
  357. //
  358. // default row height, in pixels
  359. static const int sc_RowHeight = 25;
  360. // default row width, in pixels
  361. static const int sc_RowWidth = 500;
  362. // default fraction of the width devoted to labels
  363. static const float sc_LabelFrac = 0.33f;
  364. //
  365. // argument formatter for single-line input boxes
  366. //
  367. CSimpleFormatter::CSimpleFormatter(CPluginArg& arg)
  368.     : m_Group(NULL),
  369.       m_Input(NULL),
  370.       m_Arg(&arg)
  371. {
  372. }
  373. void CSimpleFormatter::Process(void)
  374. {
  375.     if ( !m_Input  ||  !m_Group  ||  !m_Arg.GetPointer() ) {
  376.         return;
  377.     }
  378.     string val(m_Input->value());
  379.     switch (m_Arg->GetType()) {
  380.     case CPluginArg::eInteger:
  381.         m_Arg->SetInteger(val);
  382.         break;
  383.     case CPluginArg::eDouble:
  384.         m_Arg->SetDouble(val);
  385.         break;
  386.     case CPluginArg::eString:
  387.         m_Arg->SetString(val);
  388.         break;
  389.     case CPluginArg::eFile:
  390.         m_Arg->SetFile(val);
  391.         break;
  392.     default:
  393.         LOG_POST(Error << "CSimpleFormatter: unhandled argument type");
  394.         break;
  395.     }
  396. }
  397. Fl_Widget* CSimpleFormatter::GetWidget()
  398. {
  399.     if ( !m_Group ) {
  400.         //
  401.         // create a new group for our argument
  402.         //
  403.         // default pieces of text
  404.         const char* label_text = m_Arg->GetDesc().c_str();
  405.         const char* initial_value = m_Arg->AsString().c_str();
  406.         const char* tooltip = NULL;
  407.         if (m_Arg->IsSetLong_desc()) {
  408.             tooltip = m_Arg->GetLong_desc().c_str();
  409.         }
  410.         // label and value sc_RowWidth
  411.         int label_width = int (sc_RowWidth * sc_LabelFrac);
  412.         int value_width = sc_RowWidth - label_width;
  413.         int label_y = 0;
  414.         int row_height = sc_RowHeight;
  415.         // create our input item
  416.         m_Input = NULL;
  417.         Fl_Button* button = NULL;
  418.         switch (m_Arg->GetType()) {
  419.         default:
  420.         case CPluginArg::eString:
  421.             m_Input = new Fl_Input(label_width, 0,
  422.                                    value_width, row_height);
  423.             break;
  424.         case CPluginArg::eInteger:
  425.             m_Input = new Fl_Int_Input(label_width, 0,
  426.                                      value_width, row_height);
  427.             break;
  428.         case CPluginArg::eDouble:
  429.             m_Input = new Fl_Float_Input(label_width, 0,
  430.                                        value_width, row_height);
  431.             break;
  432.         case CPluginArg::eFile:
  433.             label_y = 10;
  434.             row_height += label_y;
  435.             m_Input = new Fl_File_Input(label_width, 0,
  436.                                       value_width - 30, row_height);
  437.             // we also need a button...
  438.             button = new Fl_Button(label_width + value_width - 22, 13, 19, 19);
  439.             button->label("...");
  440.             button->callback((Fl_Callback*)&CSimpleFormatter::cb_FileOpen,
  441.                              (void*)m_Input);
  442.             break;
  443.         }
  444.         _ASSERT(m_Input);
  445.         m_Input->value(initial_value);
  446.         m_Input->color(FL_BACKGROUND2_COLOR);
  447.         m_Input->box(FL_DOWN_BOX);
  448.         m_Input->tooltip(tooltip);
  449.         m_Input->labelsize(12);
  450.         m_Input->textsize(12);
  451.         // create a label to go with this as well...
  452.         Fl_Box* label = new Fl_Box(0, 0, label_width, row_height);
  453.         label->label(label_text);
  454.         label->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT |
  455.                      FL_ALIGN_CLIP | FL_ALIGN_WRAP);
  456.         label->labelsize(12);
  457.         // create a group for this row
  458.         m_Group = new Fl_Group(0, 0, sc_RowWidth, row_height);
  459.         m_Group->add(label);
  460.         m_Group->add_resizable(*m_Input);
  461.         if (button) {
  462.             m_Group->add(button);
  463.         }
  464.         m_Group->end();
  465.     }
  466.     return m_Group;
  467. }
  468. void CSimpleFormatter::cb_FileOpen(Fl_Widget* w, void* data)
  469. {
  470.     Fl_Input* input = static_cast<Fl_Input*>(data);
  471.     if (input) {
  472.         string str = NcbiFileBrowser("Select a file", "", input->value());
  473.         if ( !str.empty() ) {
  474.             input->value(str.c_str());
  475.         }
  476.     }
  477. }
  478. //
  479. // argument formatter for check-box arguments
  480. //
  481. CButtonFormatter::CButtonFormatter(CPluginArg& arg)
  482.     : m_Button(NULL),
  483.       m_Arg(&arg)
  484. {
  485. }
  486. void CButtonFormatter::Process(void)
  487. {
  488.     if ( !m_Button  ||  !m_Arg.GetPointer() ) {
  489.         return;
  490.     }
  491.     bool checked = m_Button->value() ? true : false;
  492.     m_Arg->SetBoolean(checked);
  493. }
  494. Fl_Widget* CButtonFormatter::GetWidget()
  495. {
  496.     if ( !m_Button ) {
  497.         //
  498.         // create a new group for our argument
  499.         //
  500.         // default pieces of text
  501.         const char* label_text = m_Arg->GetDesc().c_str();
  502.         bool        initial_value = m_Arg->AsBoolean();
  503.         const char* tooltip = NULL;
  504.         if (m_Arg->IsSetLong_desc()) {
  505.             tooltip = m_Arg->GetLong_desc().c_str();
  506.         }
  507.         m_Button = new Fl_Check_Button(0, 0, sc_RowWidth, sc_RowHeight,
  508.                                        label_text);
  509.         if (initial_value) {
  510.             m_Button->value(1);
  511.         }
  512.         if (tooltip) {
  513.             m_Button->tooltip(tooltip);
  514.         }
  515.     }
  516.     return m_Button;
  517. }
  518. //
  519. // argument formatter for multiline-line input boxes
  520. //
  521. CMultiLineFormatter::CMultiLineFormatter(CPluginArg& arg)
  522.     : m_Group(NULL),
  523.       m_Input(NULL),
  524.       m_Arg(&arg)
  525. {
  526. }
  527. void CMultiLineFormatter::Process(void)
  528. {
  529.     string val(m_Input->value());
  530.     vector<string> vals;
  531.     string::iterator start = val.begin();
  532.     string::iterator curr  = val.begin();
  533.     string::iterator end   = val.end();
  534.     for ( ;  curr != end;  ++curr) {
  535.         if (*curr == ','  ||  *curr == ';') {
  536.             // tokenize
  537.             if ( start != curr ) {
  538.                 vals.push_back(string(start, curr));
  539.             }
  540.             for (++curr;  curr != end;  ++curr) {
  541.                 // skip whitespace
  542.                 if ( *curr != ','  &&
  543.                      *curr != ';'  &&
  544.                      *curr != ' '  &&
  545.                      *curr != 't'  &&
  546.                      *curr != 'n'  &&
  547.                      *curr != 'r') {
  548.                     break;
  549.                 }
  550.             }
  551.             start = curr;
  552.         } else if (*curr == '"') {
  553.             // balance double quotes
  554.             for (++curr;  curr != end  &&  *curr != '"';  ++curr) {
  555.             }
  556.         }
  557.     }
  558.     if ( start != curr ) {
  559.         vals.push_back(string(start, curr));
  560.     }
  561.     CPluginArg::TValues values;
  562.     switch (m_Arg->GetType()) {
  563.     case CPluginArg::eInteger:
  564.         ITERATE (vector<string>, iter, vals) {
  565.             CRef<CPluginValue> value(new CPluginValue());
  566.             value->SetInteger(*iter);
  567.             values.push_back(value);
  568.         }
  569.         break;
  570.     case CPluginArg::eDouble:
  571.         ITERATE (vector<string>, iter, vals) {
  572.             CRef<CPluginValue> value(new CPluginValue());
  573.             value->SetDouble(*iter);
  574.             values.push_back(value);
  575.         }
  576.         break;
  577.     case CPluginArg::eString:
  578.         ITERATE (vector<string>, iter, vals) {
  579.             CRef<CPluginValue> value(new CPluginValue());
  580.             value->SetString(*iter);
  581.             values.push_back(value);
  582.         }
  583.         break;
  584.     case CPluginArg::eFile:
  585.         ITERATE (vector<string>, iter, vals) {
  586.             CRef<CPluginValue> value(new CPluginValue());
  587.             value->SetFile(*iter);
  588.             values.push_back(value);
  589.         }
  590.         break;
  591.     default:
  592.         LOG_POST(Error << "CMultiLineFormatter: unhandled argument type");
  593.         break;
  594.     }
  595.     m_Arg->SetList(values);
  596. }
  597. Fl_Widget* CMultiLineFormatter::GetWidget(void)
  598. {
  599.     if ( !m_Group ) {
  600.         //
  601.         // create a new group for our argument
  602.         //
  603.         // default pieces of text
  604.         const char* label_text = m_Arg->GetDesc().c_str();
  605.         string initial_value;
  606.         ITERATE (CPluginArg::TData::TArray, iter, m_Arg->GetData().GetArray()) {
  607.             if ( !initial_value.empty() ) {
  608.                 initial_value += "n";
  609.             }
  610.             initial_value += (*iter)->AsString();
  611.         }
  612.         const char* tooltip = NULL;
  613.         if (m_Arg->IsSetLong_desc()) {
  614.             tooltip = m_Arg->GetLong_desc().c_str();
  615.         }
  616.         // label and value sc_RowWidth
  617.         int label_width = int (sc_RowWidth * sc_LabelFrac);
  618.         int value_width = sc_RowWidth - label_width;
  619.         int label_y = 0;
  620.         int row_height = sc_RowHeight;// * 2;
  621.         // create our input item
  622.         m_Input = new Fl_Input(label_width, 0,
  623.                                value_width, row_height);
  624.         _ASSERT(m_Input);
  625.         m_Input->value(initial_value.c_str());
  626.         m_Input->box(FL_DOWN_BOX);
  627.         m_Input->color(FL_BACKGROUND2_COLOR);
  628.         m_Input->tooltip(tooltip);
  629.         m_Input->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_TOP);
  630.         m_Input->labelsize(12);
  631.         m_Input->textsize(12);
  632.         // create a label to go with this as well...
  633.         Fl_Box* label = new Fl_Box(0, 0, label_width, row_height);
  634.         label->label(label_text);
  635.         label->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT |
  636.                      FL_ALIGN_CLIP | FL_ALIGN_WRAP);
  637.         label->labelsize(12);
  638.         // create a group for this row
  639.         m_Group = new Fl_Group(0, 0, sc_RowWidth, row_height);
  640.         m_Group->add(label);
  641.         m_Group->add_resizable(*m_Input);
  642.         m_Group->end();
  643.     }
  644.     return m_Group;
  645. }
  646. //
  647. // CMenuFormatter handles items with 'set' constraints
  648. //
  649. CMenuFormatter::CMenuFormatter(CPluginArg& arg)
  650.     : m_Group(NULL),
  651.       m_Choice(NULL),
  652.       m_Arg(&arg)
  653. {
  654.     _ASSERT(arg.GetConstraint().front()->Which() ==
  655.             CPluginValueConstraint::e_Set);
  656. }
  657. void CMenuFormatter::Process(void)
  658. {
  659.     string val = m_Choice->text();
  660.     switch (m_Arg->GetType()) {
  661.     case CPluginArg::eInteger:
  662.         m_Arg->SetInteger(val);
  663.         break;
  664.     case CPluginArg::eDouble:
  665.         m_Arg->SetDouble(val);
  666.         break;
  667.     case CPluginArg::eString:
  668.         m_Arg->SetString(val);
  669.         break;
  670.     case CPluginArg::eFile:
  671.         m_Arg->SetFile(val);
  672.         break;
  673.     default:
  674.         break;
  675.     }
  676. }
  677. Fl_Widget* CMenuFormatter::GetWidget()
  678. {
  679.     if ( !m_Group ) {
  680.         //
  681.         // create a new group for our argument
  682.         //
  683.         // default pieces of text
  684.         const char* label_text = m_Arg->GetDesc().c_str();
  685.         const char* initial_value = m_Arg->AsString().c_str();
  686.         const char* tooltip = NULL;
  687.         if (m_Arg->IsSetLong_desc()) {
  688.             tooltip = m_Arg->GetLong_desc().c_str();
  689.         }
  690.         // label and value sc_RowWidth
  691.         int label_width = int (sc_RowWidth * sc_LabelFrac);
  692.         int value_width = sc_RowWidth - label_width;
  693.         int label_y = 0;
  694.         int row_height = sc_RowHeight;
  695.         //
  696.         // create our menu
  697.         //
  698.         m_Choice = new Fl_Choice(label_width, 0, value_width, row_height);
  699.         _ASSERT(m_Choice);
  700.         int default_val = m_Choice->add("");
  701.         string val = m_Arg->AsString();
  702.         ITERATE (CPluginValueConstraint::TSet, set_iter,
  703.                  m_Arg->GetConstraint().front()->GetSet()) {
  704.             string str = *set_iter;
  705.             string::size_type pos = 0;
  706.             while ( (pos = str.find_first_of("/", pos)) != string::npos) {
  707.                 str.insert(pos, "\");
  708.                 pos += 2;
  709.             }
  710.             int idx = m_Choice->add(str.c_str());
  711.             if (*set_iter == val) {
  712.                 default_val = idx;
  713.             }
  714.         }
  715.         m_Choice->value(default_val);
  716.         //m_Choice->box(FL_DOWN_BOX);
  717.         m_Choice->color(FL_BACKGROUND2_COLOR);
  718.         m_Choice->tooltip(tooltip);
  719.         m_Choice->labelsize(12);
  720.         m_Choice->textsize(12);
  721.         // create a label to go with this as well...
  722.         Fl_Box* label = new Fl_Box(0, 0, label_width, row_height);
  723.         label->label(label_text);
  724.         label->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT |
  725.                      FL_ALIGN_CLIP | FL_ALIGN_WRAP);
  726.         label->labelsize(12);
  727.         // create a group for this row
  728.         m_Group = new Fl_Group(0, 0, sc_RowWidth, row_height);
  729.         m_Group->add(label);
  730.         m_Group->add_resizable(*m_Choice);
  731.         m_Group->end();
  732.     }
  733.     return m_Group;
  734. }
  735. //
  736. // CMultiObjFormatter formats the values stored in a multi-column
  737. // list browser as CObjects
  738. //
  739. CMultiObjFormatter::CMultiObjFormatter(CPluginArg& arg,
  740.                                        const TConstScopedObjects& objs)
  741.     : m_Group(NULL),
  742.       m_Browser(NULL),
  743.       m_Arg(&arg),
  744.       m_Objects(objs)
  745. {
  746. }
  747. CMultiObjFormatter::~CMultiObjFormatter()
  748. {
  749. static void
  750. scb_OnPopupBrowser(Fl_Widget* w, void* data)
  751. {
  752.     CObjBrowser* browser = static_cast<CObjBrowser*>(data);
  753.     if (browser) {
  754.         browser->ShowBrowseDlg();
  755.     }
  756. }
  757. Fl_Widget* CMultiObjFormatter::GetWidget()
  758. {
  759.     if ( !m_Group ) {
  760.         //
  761.         // create a new group for our argument
  762.         //
  763.         // default pieces of text
  764.         const char* label_text = m_Arg->GetDesc().c_str();
  765.         const char* tooltip = NULL;
  766.         if (m_Arg->IsSetLong_desc()) {
  767.             tooltip = m_Arg->GetLong_desc().c_str();
  768.         }
  769.         // label and value sc_RowWidth
  770.         const int label_y = 0;
  771.         const int button_size = 19;
  772.         const int label_width = int (sc_RowWidth * sc_LabelFrac);
  773.         const int value_width = sc_RowWidth - label_width - button_size - 5;
  774.         const int row_height = sc_RowHeight * 5;
  775.         const int button_x = label_width + value_width + 5;
  776.         const int button_y = label_y + row_height / 2 - button_size / 2;
  777.         //
  778.         // create our selector
  779.         //
  780.         Fl_Group* parent = new Fl_Group(0, 0,
  781.                                         label_width + value_width, row_height);
  782.         m_Browser = new CObjBrowser(parent->x(), parent->y(),
  783.                                     parent->w(), parent->h(),
  784.                                     m_Arg->GetObjectSubtype(), label_text);
  785.         _ASSERT(m_Browser);
  786.         m_Browser->Reserve(m_Arg->GetData().GetArray().size());
  787.         set<const CObject*> obj_ptrs;
  788.         ITERATE (TConstScopedObjects, iter, m_Objects) {
  789.             const CObject* obj = iter->object;
  790.             const IDocument* doc =
  791.                 CDocManager::GetDocumentFromScope(*iter->scope);
  792.             if (doc  &&  obj  &&
  793.                 obj_ptrs.find(obj) == obj_ptrs.end()) {
  794.                 m_Browser->Add(*doc, *obj);
  795.                 obj_ptrs.insert(obj);
  796.             }
  797.         }
  798.         m_Browser->tooltip(tooltip);
  799.         m_Browser->box(FL_THIN_DOWN_FRAME);
  800.         m_Browser->labelsize(12);
  801.         parent->end();
  802.         parent->resizable(m_Browser);
  803.         parent->box(FL_DOWN_BOX);
  804.         parent->color(FL_BACKGROUND2_COLOR);
  805.         // ...add a button to launch the select from other dialog
  806.         Fl_Button* button = new Fl_Button(button_x, button_y,
  807.                                           button_size, button_size, "...");
  808.         button->callback(scb_OnPopupBrowser, m_Browser);
  809.         // create a group for this row
  810.         m_Group = new Fl_Group(0, 0, sc_RowWidth, row_height);
  811.         //m_Group->add(label);
  812.         m_Group->add_resizable(*parent);
  813.         m_Group->add(button);
  814.         m_Group->end();
  815.     }
  816.     return m_Group;
  817. }
  818. void CMultiObjFormatter::Process(void)
  819. {
  820.     if ( !m_Browser ) {
  821.         return;
  822.     }
  823.     CPluginArg::TValues value_list;
  824.     for (size_t i = 0;  i < m_Browser->GetRows();  ++i) {
  825.         const SBrowserObject& obj = m_Browser->GetData(i);
  826.         CRef<CPluginValue> value(new CPluginValue);
  827.         value->SetObject(*obj.document, *obj.object);
  828.         value_list.push_back(value);
  829.     }
  830.     if (value_list.size()) {
  831.         m_Arg->SetObject(value_list);
  832.     }
  833. }
  834. //
  835. // CSingleObjFormatter formats the values stored in an Fl_Choice 
  836. // as CObjects
  837. //
  838. CSingleObjFormatter::CSingleObjFormatter(CPluginArg& arg,
  839.                                          const TConstScopedObjects& objs)
  840.     : m_Group(NULL),
  841.       m_Choice(NULL),
  842.       m_Arg(&arg),
  843.       m_Objects(objs)
  844. {
  845. }
  846. Fl_Widget* CSingleObjFormatter::GetWidget()
  847. {
  848.     if ( !m_Group ) {
  849.         //
  850.         // create a new group for our argument
  851.         //
  852.         // default pieces of text
  853.         const char* label_text = m_Arg->GetDesc().c_str();
  854.         const char* tooltip = NULL;
  855.         if (m_Arg->IsSetLong_desc()) {
  856.             tooltip = m_Arg->GetLong_desc().c_str();
  857.         }
  858.         // label and value sc_RowWidth
  859.         int label_width = int (sc_RowWidth * sc_LabelFrac);
  860.         int value_width = sc_RowWidth - label_width;
  861.         int label_y = 0;
  862.         int row_height = sc_RowHeight;
  863.         //
  864.         // create our menu
  865.         //
  866.         m_Choice = new CObjChoice(label_width, 0, value_width, row_height,
  867.                                   m_Arg->GetObjectSubtype());
  868.         _ASSERT(m_Choice);
  869.         set<const CObject*> obj_ptrs;
  870.         ITERATE (TConstScopedObjects, iter, m_Objects) {
  871.             const CObject* obj = iter->object;
  872.             const IDocument* doc =
  873.                 CDocManager::GetDocumentFromScope(*iter->scope);
  874.             if (doc  &&  obj  &&
  875.                 obj_ptrs.find(obj) == obj_ptrs.end()) {
  876.                 m_Choice->Add(*doc, *obj);
  877.             }
  878.         }
  879.         m_Choice->color(FL_BACKGROUND2_COLOR);
  880.         m_Choice->tooltip(tooltip);
  881.         m_Choice->labelsize(12);
  882.         m_Choice->textsize(12);
  883.         // create a label to go with this as well...
  884.         Fl_Box* label = new Fl_Box(0, 0, label_width, row_height);
  885.         label->label(label_text);
  886.         label->align(FL_ALIGN_INSIDE | FL_ALIGN_RIGHT |
  887.                      FL_ALIGN_CLIP | FL_ALIGN_WRAP);
  888.         label->labelsize(12);
  889.         // create a group for this row
  890.         m_Group = new Fl_Group(0, 0, sc_RowWidth, row_height);
  891.         m_Group->add(label);
  892.         m_Group->add_resizable(*m_Choice);
  893.         m_Group->end();
  894.     }
  895.     return m_Group;
  896. }
  897. void CSingleObjFormatter::Process(void)
  898. {
  899.     if ( !m_Choice ) {
  900.         return;
  901.     }
  902.     SConstScopedObject obj = m_Choice->GetSelection();
  903.     const IDocument* doc = CDocManager::GetDocumentFromScope(*obj.scope);
  904.     if (obj.object.GetPointer()  &&  doc) {
  905.         m_Arg->SetObject(*doc, *obj.object);
  906.     }
  907. }
  908. ////////////////////////////////////////////////////////////////////////////
  909. //
  910. // panel widget to organize flag arguments
  911. //
  912. CFlagPanel::CFlagPanel(CPluginArgSet::Tdata& args)
  913.     : m_Group(NULL)
  914. {
  915.     TConstScopedObjects objs;
  916.     NON_CONST_ITERATE (CPluginArgSet::Tdata, iter, args) {
  917.         CPluginArg& arg = **iter;
  918.         CRef<CArgFormatter> fmt
  919.             (CPluginArgForm::GetFormatter(arg, objs));
  920.         if (fmt) {
  921.             m_Formatters.push_back(fmt);
  922.         }
  923.     }
  924.     size_t right = m_Formatters.size() / 2;
  925.     size_t left  = m_Formatters.size() - right;
  926.     size_t left_ht  = 0;
  927.     size_t right_ht = 0;
  928.     size_t idx = 0;
  929.     NON_CONST_ITERATE (list< CRef<CArgFormatter> >, iter, m_Formatters) {
  930.         Fl_Widget* widget = (*iter)->GetWidget();
  931.         if (idx < left) {
  932.             left_ht += widget->h();
  933.         } else {
  934.             right_ht += widget->h();
  935.         }
  936.         ++idx;
  937.     }
  938.     m_Group = new Fl_Group(0, 0, sc_RowWidth, max(left_ht, right_ht));
  939.     idx = 0;
  940.     left_ht = 0;
  941.     right_ht = 0;
  942.     NON_CONST_ITERATE (list< CRef<CArgFormatter> >, iter, m_Formatters) {
  943.         Fl_Widget* widget = (*iter)->GetWidget();
  944.         if (idx < left) {
  945.             widget->resize(0, left_ht, sc_RowWidth / 2, widget->h());
  946.             left_ht += widget->h();
  947.         } else {
  948.             widget->resize(sc_RowWidth / 2, right_ht, sc_RowWidth / 2, widget->h());
  949.             right_ht += widget->h();
  950.         }
  951.         m_Group->add(widget);
  952.         ++idx;
  953.     }
  954.     m_Group->end();
  955. }
  956. void CFlagPanel::Process()
  957. {
  958.     NON_CONST_ITERATE (list< CRef<CArgFormatter> >, iter, m_Formatters) {
  959.         (*iter)->Process();
  960.     }
  961. }
  962. Fl_Widget* CFlagPanel::GetWidget()
  963. {
  964.     return m_Group;
  965. }
  966. END_NCBI_SCOPE
  967. /*
  968.  * ===========================================================================
  969.  * $Log: plugin_arg_form.cpp,v $
  970.  * Revision 1000.0  2004/06/01 21:17:08  gouriano
  971.  * PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.1
  972.  *
  973.  * Revision 1.1  2004/06/01 18:04:44  dicuccio
  974.  * Initial revision.  Lots of changes: added gui_project ASN.1 project, added new
  975.  * plugin arg form (separate widget), added plugin selector dialog
  976.  *
  977.  * ===========================================================================
  978.  */