00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
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
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
00071 m_Control = new CMapControl(this);
00072 m_Control->SetStyle(CMapControl::fSingleSelection);
00073
00074
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
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
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
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
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
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
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& )
00223 {
00224 _ASSERT(false);
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
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();
00254 item.Expand(expand);
00255 item.SetIcon(expand ? m_OpenIcon : m_ClosedIcon);
00256
00257
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
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
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, int state,
00357 SwxMapItemProperties& props)
00358 {
00359 wxRect rc_back(m_Rect);
00360 rc_back.Inflate(-props.m_Border, -props.m_Border);
00361
00362
00363
00364
00365
00366 x_DrawBackground(dc, rc_back, state, props);
00367
00368 bool selected = (state & CSelectionControl::fItemSelected) != 0;
00369
00370
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
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
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
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