src/gui/widgets/wx/group_map_widget.cpp

Go to the documentation of this file.
00001 /*  $Id: group_map_widget.cpp 19865 2009-08-14 18:37:26Z kuznets $
00002  * ===========================================================================
00003  *
00004  *                            PUBLIC DOMAIN NOTICE
00005  *               National Center for Biotechnology Information
00006  *
00007  *  This software/database is a "United States Government Work" under the
00008  *  terms of the United States Copyright Act.  It was written as part of
00009  *  the author's official duties as a United States Government employee and
00010  *  thus cannot be copyrighted.  This software/database is freely available
00011  *  to the public for use. The National Library of Medicine and the U.S.
00012  *  Government have not placed any restriction on its use or reproduction.
00013  *
00014  *  Although all reasonable efforts have been taken to ensure the accuracy
00015  *  and reliability of the software and data, the NLM and the U.S.
00016  *  Government do not and cannot warrant the performance or results that
00017  *  may be obtained by using this software or data. The NLM and the U.S.
00018  *  Government disclaim all warranties, express or implied, including
00019  *  warranties of performance, merchantability or fitness for any particular
00020  *  purpose.
00021  *
00022  *  Please cite the author in any work or product based on this material.
00023  *
00024  * ===========================================================================
00025  *
00026  * Authors:  Andrey Yazhuk
00027  *
00028  */
00029 
00030 #include <ncbi_pch.hpp>
00031 #include <corelib/ncbistd.hpp>
00032 
00033 #include <gui/widgets/wx/group_map_widget.hpp>
00034 #include <gui/widgets/wx/fileartprov.hpp>
00035 #include <gui/widgets/wx/wx_utils.hpp>
00036 
00037 #include <wx/dcbuffer.h>
00038 #include <wx/sizer.h>
00039 
00040 
00041 BEGIN_NCBI_SCOPE
00042 
00043 ///////////////////////////////////////////////////////////////////////////////
00044 /// CGroupMapWidget
00045 
00046 bool CGroupMapWidget::m_IconsRegistered = 0;
00047 
00048 CGroupMapWidget::CGroupMapWidget(wxWindow* parent,
00049                                       wxWindowID id,
00050                                       const wxPoint& pos,
00051                                       const wxSize& size,
00052                                       long style,
00053                                       const wxString& name)
00054 :   TParent(parent, id, pos, size, style, name)
00055 {
00056     // register only once
00057     static bool icons_registered = false;
00058     if( ! m_IconsRegistered)    {
00059         wxFileArtProvider* provider = GetDefaultFileArtProvider();
00060         provider->RegisterFileAlias(_T("map::arrow_open"),
00061                                     _T("arrow_open.png"));
00062         provider->RegisterFileAlias(_T("map::arrow_close"),
00063                                     _T("arrow_close.png"));
00064         icons_registered = true;
00065     }
00066 
00067     m_OpenIcon = wxArtProvider::GetBitmap(_T("map::arrow_open"));
00068     m_ClosedIcon = wxArtProvider::GetBitmap(_T("map::arrow_close"));
00069 
00070     // Create and setup Map Control
00071     m_Control = new CMapControl(this);
00072     m_Control->SetStyle(CMapControl::fSingleSelection);
00073 
00074     // Adjust Map Control settings
00075     CMapControl::SProperties& props = m_Control->GetProperties();
00076     props.m_SingleColumn = false;
00077     props.m_ItemOffsetX = 1;
00078     props.m_ItemOffsetY = 0;
00079     props.m_SepLineWidth = 1;
00080     props.m_ColumnWidth = 200;
00081     props.m_SeparateGroups = false;
00082     props.m_SizePolicy = CMapControl::eAdjustVertSize;
00083 
00084     // adjust Map Control Item settings
00085     SwxMapItemProperties& it_props = m_Control->GetMapItemProperties();
00086     it_props.m_BackColor = m_Control->GetBackgroundColour();
00087     it_props.m_TextColor = wxColour(0, 0, 64);
00088     it_props.m_VertMargin = 2;
00089     it_props.m_HorzMargin = 2;
00090 
00091     wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
00092     sizer->Add(m_Control, 1, wxEXPAND);
00093     SetSizer(sizer);
00094 }
00095 
00096 
00097 CGroupMapWidget::~CGroupMapWidget()
00098 {
00099     Clear();
00100     //m_Control->RemoveListener(this);
00101 }
00102 
00103 
00104 void CGroupMapWidget::Init(const TGroupDescrVector& groups)
00105 {
00106     Clear();
00107 
00108     for(size_t i = 0;  i < groups.size();  i++ )    {
00109         const SGroupDescr& grp = groups[i];
00110         AddGroup(grp.m_Label, grp.m_Expanded);
00111 
00112         const TItemDescrVector& items = grp.m_Items;
00113         for(  size_t j = 0;  j < items.size();  j++ )   {
00114             const SItemDescr& item = items[j];
00115             AddItem(grp.m_Label, item.m_Label, item.m_IconAlias);
00116         }
00117     }
00118     //m_Scroll->UpdateScrollBars();
00119 
00120     int n =  m_Control->GetItemsCount();
00121     if(n > 0)   {
00122         m_Control->SelectItem(0);
00123     }
00124 }
00125 
00126 
00127 void CGroupMapWidget::Clear()
00128 {
00129     m_Control->DeleteAllItems();
00130 
00131     for( size_t i = 0;  i < m_Groups.size();  i++ ) {
00132         delete m_Groups[i];
00133     }
00134     m_Groups.clear();
00135 }
00136 
00137 
00138 void CGroupMapWidget::AddGroup(const string& label, bool expand)
00139 {
00140     int index = x_GetGroupIndex(label);
00141     if(index == -1) {
00142         // add new group
00143         SGroup* grp = new SGroup();
00144         grp->m_GroupItem =
00145             new CGroupItem(label, expand ? m_OpenIcon : m_ClosedIcon, "", *this, true);
00146         grp->m_GroupItem->Expand(expand);
00147         m_Groups.push_back(grp);
00148 
00149         m_Control->AddItem(grp->m_GroupItem.GetPointer());
00150     } else {
00151         string s = "Group \"" + label + "\" already exist";
00152         NCBI_THROW(CException, eUnknown, s);
00153     }
00154 }
00155 
00156 
00157 typedef CMapControl::TIndex TIndex;
00158 
00159 void CGroupMapWidget::AddItem(const string& group_label, const string& label,
00160                               const string& icon_alias)
00161 {
00162     int index = x_GetGroupIndex(group_label);
00163     if(index != -1) {
00164         // add new group
00165         SGroup* grp = m_Groups[index];
00166 
00167         wxBitmap icon = wxArtProvider::GetBitmap(ToWxString(icon_alias));
00168         TItemRef    ref(new CGroupItem(label, icon, "", *this, false));
00169         grp->m_Items.push_back(ref);
00170 
00171         // update Control if needed
00172         if(grp->m_GroupItem->IsExpanded())  {
00173              TIndex i_grp = m_Control->GetItemIndex(*grp->m_GroupItem);
00174              TIndex ins = i_grp + grp->m_Items.size();
00175              m_Control->InsertItem(ins, ref.GetPointer());
00176         }
00177     } else {
00178         string s = "Group \"" + group_label + "\" does not exist.";
00179         NCBI_THROW(CException, eUnknown, s);
00180     }
00181 }
00182 
00183 
00184 void CGroupMapWidget::GetGroupLabels(vector<string>& groups) const
00185 {
00186     for( size_t i = 0;  i < m_Groups.size();  i++ ) {
00187         const SGroup* grp = m_Groups[i];
00188         groups.push_back(grp->m_GroupItem->GetLabel());
00189     }
00190 }
00191 
00192 
00193 bool CGroupMapWidget::IsExpanded(const string& group) const
00194 {
00195     int index = x_GetGroupIndex(group);
00196     if(index >= 0)  {
00197         const SGroup* grp = m_Groups[index];
00198         return grp->m_GroupItem->IsExpanded();
00199     } else {
00200         string s = "Group \"" + group + "\" does not exist.";
00201         NCBI_THROW(CException, eUnknown, s);
00202     }
00203     return false;
00204 }
00205 
00206 
00207 string CGroupMapWidget::GetSelectedItem() const
00208 {
00209     int index = m_Control->GetSelectedIndex();
00210     if(index >=0 )  {
00211         CMapControl::TCItemRef item = m_Control->GetItem(index);
00212         const CGroupItem* grp_item = dynamic_cast<const CGroupItem*>(item.GetPointer());
00213         _ASSERT(grp_item);
00214         if(grp_item  &&  ! grp_item->IsGroupSeparator())    {
00215             return grp_item->GetLabel();
00216         }
00217     }
00218     return "";
00219 }
00220 
00221 
00222 void CGroupMapWidget::ExpandGroup(const string& /*label*/)
00223 {
00224     _ASSERT(false); // TODO implement
00225 }
00226 
00227 
00228 CMapControl* CGroupMapWidget::GetMapControl()
00229 {
00230     return m_Control;
00231 }
00232 
00233 
00234 int CGroupMapWidget::x_GetGroupIndex(const string& label) const
00235 {
00236     for(size_t i = 0; i < m_Groups.size(); i++ )    {
00237         CGroupItem* item = m_Groups[i]->m_GroupItem;
00238         if(item->GetLabel() == label)   {
00239             return i;
00240         }
00241     }
00242     return -1;
00243 }
00244 
00245 
00246 void CGroupMapWidget::x_OnToggleGroup(CGroupItem& item)
00247 {
00248     // find the group descriptor
00249     int grp_i = x_GetGroupIndex(item.GetLabel());
00250     _ASSERT(grp_i >= 0);
00251     TMapItems& v_items = m_Groups[grp_i]->m_Items;
00252 
00253     bool expand = ! item.IsExpanded();//  &&  ! v_item.size();
00254     item.Expand(expand);
00255     item.SetIcon(expand ? m_OpenIcon : m_ClosedIcon);
00256 
00257     // get group iem index in the Control
00258     TIndex index = m_Control->GetItemIndex(item);
00259 
00260     m_Control->LockUpdates(true);
00261 
00262     for( size_t i = 0;  i < v_items.size();  i++  ) {
00263         if(expand)  {
00264             TItemRef mp_it = v_items[i];
00265             m_Control->InsertItem(++index, mp_it.GetPointer());
00266         } else {
00267             m_Control->DeleteItem(index + 1);
00268         }
00269     }
00270 
00271     m_Control->LockUpdates(false);
00272     //m_Scroll->UpdateScrollBars();
00273 }
00274 
00275 
00276 void CGroupMapWidget::x_OnSelectItem(CGroupItem& item)
00277 {
00278     wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, GetId());
00279     event.SetEventObject(this);
00280     event.SetString(ToWxString(item.GetLabel()));
00281 
00282     (void)GetEventHandler()->ProcessEvent(event);
00283 }
00284 
00285 
00286 ///////////////////////////////////////////////////////////////////////////////
00287 /// CGroupItem
00288 
00289 CGroupMapWidget::CGroupItem::CGroupItem(const string& label,
00290                                               wxBitmap& icon,
00291                                               const string& description,
00292                                               CGroupMapWidget& widget,
00293                                               bool group)
00294 :   CMapItem(label, icon, description, group),
00295     m_Widget(widget),
00296     m_Expanded(true),
00297     m_HotLabel(false)
00298 {
00299 }
00300 
00301 
00302 bool CGroupMapWidget::CGroupItem::IsExpanded() const
00303 {
00304     return m_Expanded;
00305 }
00306 
00307 
00308 void CGroupMapWidget::CGroupItem::Expand(bool exp)
00309 {
00310     m_Expanded = exp;
00311 }
00312 
00313 
00314 int CGroupMapWidget::CGroupItem::PreferredHeight(wxDC& dc,
00315                                                    SwxMapItemProperties& props,
00316                                                    int width)
00317 {
00318     int pref_h = 0;
00319     if(m_Icon.IsOk()) {
00320         pref_h = m_Icon.GetHeight();
00321     }
00322 
00323     int label_h = x_PreferredLabelHeight(dc, props, width);
00324 
00325     pref_h = max(pref_h, label_h);
00326     if(IsGroupSeparator())  {
00327         pref_h += 6;
00328     } else {
00329         pref_h += props.m_VertMargin * 2;
00330     }
00331     if(m_Separator) {
00332         pref_h += x_PreferredSeparatorHeight(dc);
00333     }
00334     return pref_h;
00335 }
00336 
00337 
00338 int CGroupMapWidget::CGroupItem::x_GetItemShift() const
00339 {
00340     return IsGroupSeparator() ? 0 : 12;
00341 }
00342 
00343 
00344 void CGroupMapWidget::CGroupItem::Layout(wxDC& dc, SwxMapItemProperties& props)
00345 {
00346     CMapItem::Layout(dc, props);
00347 
00348     wxFont font = props.m_Font;
00349     font.SetWeight(wxFONTWEIGHT_NORMAL);
00350     dc.SetFont(font);
00351 
00352     m_LabelRealW = x_CalculateRealTextWidth(dc, props, true);
00353 }
00354 
00355 
00356 void CGroupMapWidget::CGroupItem::Draw(wxDC& dc/*, const wxRect& rc*/, int state,
00357                                            SwxMapItemProperties& props)
00358 {
00359     wxRect rc_back(m_Rect);
00360     rc_back.Inflate(-props.m_Border, -props.m_Border);
00361 
00362     // draw focus rectangle
00363     //x_DrawFocusRect(dc, rc_back, state, props); //rc
00364 
00365     // Fill background
00366     x_DrawBackground(dc, rc_back, state, props);
00367 
00368     bool selected = (state & CSelectionControl::fItemSelected) != 0;
00369 
00370     // Draw Icon
00371     if(m_Icon.Ok()) {
00372         dc.DrawBitmap(m_Icon, m_IconPos.x, m_IconPos.y, true);
00373     }
00374 
00375     if( ! m_Label.empty()  &&  m_LabelRect.width > 0  &&  m_LabelRect.height > 0)  {
00376         bool widget_focused = (state & CSelectionControl::fWidgetFocused) != 0;
00377 
00378         if(IsGroupSeparator())  {
00379             dc.SetFont(props.m_Font);
00380         } else {
00381             // TODO this can be optimized
00382             wxFont font = props.m_Font;
00383             font.SetWeight(wxFONTWEIGHT_NORMAL);
00384             dc.SetFont(font);
00385         }
00386 
00387         x_DrawText(dc, m_Label, m_LabelRect, selected, widget_focused, props);
00388         // Draw Description
00389         if( ! m_Descr.empty()  &&  m_DescrRect.width > 0  &&  m_DescrRect.height > 0)  {
00390             dc.SetFont(props.m_MinorFont);
00391             x_DrawText(dc, m_Descr, m_DescrRect, selected, widget_focused, props);
00392         }
00393     }
00394 }
00395 
00396 
00397 int CGroupMapWidget::CGroupItem::x_PreferredSeparatorHeight(wxDC& dc) const
00398 {
00399     return 0;
00400 }
00401 
00402 void CGroupMapWidget::CGroupItem::x_DrawBackground(wxDC& dc, const wxRect& rc,
00403                                                        int state, SwxMapItemProperties& props)
00404 {
00405     bool selected = (state & CSelectionControl::fItemSelected) != 0;
00406     wxColour cl_back = selected ? props.m_SelBackColor :
00407         (IsGroupSeparator() ? GetAverage(props.m_TextColor, props.m_BackColor, 0.10f)
00408                             : props.m_BackColor);
00409     
00410     if(!IsGroupSeparator() && m_HotLabel)  {
00411         const float     kBlueAdjustment = 0.1f;
00412         unsigned char   adjustedRed = cl_back.Red() * (1 - kBlueAdjustment);
00413         unsigned char   adjustedGreen = cl_back.Green() * (1 - kBlueAdjustment);
00414         cl_back.Set(adjustedRed, adjustedGreen, cl_back.Blue(), cl_back.Alpha());
00415     }
00416 
00417     wxBrush brush(cl_back);
00418     dc.SetBrush(brush);
00419     dc.DrawRectangle(rc.x, rc.y, rc.width, rc.height);
00420 }
00421 
00422 
00423 void CGroupMapWidget::CGroupItem::OnDefaultAction()
00424 {
00425     if(IsGroupSeparator())  {
00426         m_Widget.x_OnToggleGroup(*this);
00427     } else {
00428         m_Widget.x_OnSelectItem(*this);
00429     }
00430 }
00431 
00432 
00433 bool CGroupMapWidget::CGroupItem::OnHotTrack(const wxPoint& ms_pos)
00434 {
00435     if (IsGroupSeparator()) 
00436     {
00437         // make all separator hot clickable item (including icon)
00438         return true;
00439     }
00440     wxRect rc(m_LabelRect);
00441     rc.width = m_LabelRealW;
00442     m_HotLabel = rc.Contains(ms_pos);
00443     return m_HotLabel;
00444 }
00445 
00446 
00447 END_NCBI_SCOPE
00448 
00449 

Generated on Sun Dec 6 22:32:34 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:21:05 2009 by modify_doxy.py rev. 173732