navpane.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // NavPane
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. class NavPaneImpl : public NavPane {
  8. private:
  9. //////////////////////////////////////////////////////////////////////////////
  10. //
  11. // Types
  12. //
  13. //////////////////////////////////////////////////////////////////////////////
  14. class Topic : public Pane {
  15. public:
  16. TRef<Topic> m_ptopicParent;
  17. TRef<Pane> m_ppane;
  18. TRef<ModifiableString> m_pstring;
  19. TRef<ModifiableColorValue> m_pcolor;
  20. ZString m_str;
  21. ZString m_strMain;
  22. ZString m_strSecondary;
  23. int m_indent;
  24. Color m_color;
  25. Color m_colorHighlight;
  26. bool m_bInside;
  27. TRef<StringEventSourceImpl> m_peventSource;
  28. Topic(
  29. StringEventSourceImpl* peventSource,
  30. Topic* ptopicParent,
  31. IEngineFont* pfont,
  32. int indent,
  33. int width,
  34. const ZString& str,
  35. const ZString& strMain,
  36. const ZString& strSecondary,
  37. const Color& colorHighlight
  38. ) :
  39. m_peventSource(peventSource),
  40. m_ptopicParent(ptopicParent),
  41. m_str(str),
  42. m_strMain(strMain),
  43. m_strSecondary(strSecondary),
  44. m_indent(indent * 8),
  45. m_colorHighlight(colorHighlight),
  46. m_bInside(false)
  47. {
  48. m_ppane =
  49. new AnimatedImagePane(
  50. CreateStringImage(
  51. JustifyLeft(),
  52. pfont,
  53. m_pcolor = new ModifiableColorValue(Color::White()),
  54. width - m_indent,
  55. m_pstring = new ModifiableString(str),
  56. 4
  57. )
  58. );
  59. InternalSetOffset(m_ppane, WinPoint(m_indent, 0));
  60. InsertAtBottom(m_ppane);
  61. }
  62. void SetColor(const Color& color)
  63. {
  64. m_color = color;
  65. if (!m_bInside) {
  66. m_pcolor->SetValue(color);
  67. }
  68. }
  69. Pane* GetPane()
  70. {
  71. return this;
  72. }
  73. //////////////////////////////////////////////////////////////////////////////
  74. //
  75. // Pane methods
  76. //
  77. //////////////////////////////////////////////////////////////////////////////
  78. void UpdateLayout()
  79. {
  80. Child()->UpdateLayout();
  81. InternalSetSize(WinPoint(
  82. Child()->XSize() + m_indent,
  83. Child()->YSize()
  84. ));
  85. }
  86. //////////////////////////////////////////////////////////////////////////////
  87. //
  88. // IMouseInput methods
  89. //
  90. //////////////////////////////////////////////////////////////////////////////
  91. void MouseEnter(IInputProvider* pprovider, const Point& point)
  92. {
  93. m_bInside = true;
  94. m_pcolor->SetValue(m_colorHighlight);
  95. }
  96. void MouseLeave(IInputProvider* pprovider)
  97. {
  98. m_bInside = false;
  99. m_pcolor->SetValue(m_color);
  100. }
  101. MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
  102. {
  103. if (button == 0 && bDown) {
  104. m_peventSource->Trigger(m_strMain);
  105. }
  106. return MouseResult();
  107. }
  108. };
  109. typedef TList<TRef<Topic> > TopicList;
  110. //////////////////////////////////////////////////////////////////////////////
  111. //
  112. // Members
  113. //
  114. //////////////////////////////////////////////////////////////////////////////
  115. TopicList m_listTopic;
  116. TRef<StringEventSourceImpl> m_peventSource;
  117. TRef<IEngineFont> m_pfont;
  118. TRef<ColumnPane> m_pcolumn;
  119. TRef<Topic> m_ptopicSelected;
  120. Color m_color;
  121. Color m_colorSelected;
  122. Color m_colorHighlight;
  123. public:
  124. //////////////////////////////////////////////////////////////////////////////
  125. //
  126. // Constructor
  127. //
  128. //////////////////////////////////////////////////////////////////////////////
  129. NavPaneImpl(
  130. IObjectList* plist,
  131. const Point& size,
  132. const Color& color,
  133. const Color& colorSelected,
  134. const Color& colorHighlight,
  135. IEngineFont* pfont
  136. ) :
  137. m_color(color),
  138. m_colorSelected(colorSelected),
  139. m_colorHighlight(colorHighlight),
  140. m_pfont(pfont)
  141. {
  142. m_peventSource = new StringEventSourceImpl();
  143. InternalSetSize(WinPoint::Cast(size));
  144. m_pcolumn = new ColumnPane();
  145. InsertAtBottom(m_pcolumn);
  146. ReadTopicList(plist, 0, NULL);
  147. m_ptopicSelected = m_listTopic.GetFront();
  148. UpdatePanes();
  149. }
  150. //////////////////////////////////////////////////////////////////////////////
  151. //
  152. // Implementation methods
  153. //
  154. //////////////////////////////////////////////////////////////////////////////
  155. void ReadTopicList(IObjectList* plist, int indent, Topic* ptopicParent)
  156. {
  157. plist->GetFirst();
  158. while (plist->GetCurrent() != NULL) {
  159. TRef<IObjectPair> ppair; CastTo(ppair, plist->GetCurrent());
  160. TRef<StringValue> pstring; CastTo(pstring, ppair->GetNth(0));
  161. TRef<StringValue> pstringMain; CastTo(pstringMain, ppair->GetNth(1));
  162. TRef<StringValue> pstringSecondary; CastTo(pstringSecondary, ppair->GetNth(2));
  163. TRef<IObjectList> plistSubTopic; CastTo(plistSubTopic, ppair->GetLastNth(3));
  164. TRef<Topic> ptopic =
  165. new Topic(
  166. m_peventSource,
  167. ptopicParent,
  168. m_pfont,
  169. indent,
  170. XSize(),
  171. pstring->GetValue(),
  172. pstringMain->GetValue(),
  173. pstringSecondary->GetValue(),
  174. m_colorHighlight
  175. );
  176. m_listTopic.PushEnd(ptopic);
  177. if (plistSubTopic->GetCount() != 0) {
  178. ReadTopicList(plistSubTopic, indent + 1, ptopic);
  179. }
  180. plist->GetNext();
  181. }
  182. }
  183. bool IsTopicSelected(Topic* ptopicParent)
  184. {
  185. TRef<Topic> ptopic = m_ptopicSelected;
  186. while (ptopic != NULL) {
  187. if (ptopic == ptopicParent) {
  188. return true;
  189. }
  190. ptopic = ptopic->m_ptopicParent;
  191. }
  192. return false;
  193. }
  194. bool IsTopicOpen(Topic* ptopic)
  195. {
  196. Topic* ptopicParent = ptopic->m_ptopicParent;
  197. //
  198. // Top level topics are always open
  199. //
  200. if (ptopicParent == NULL) {
  201. return true;
  202. }
  203. //
  204. // If all of this topic parents are selected this topic is open
  205. //
  206. while (ptopicParent != NULL) {
  207. if (!IsTopicSelected(ptopicParent)) {
  208. return false;
  209. }
  210. ptopicParent = ptopicParent->m_ptopicParent;
  211. }
  212. return true;
  213. }
  214. void UpdatePanes()
  215. {
  216. m_pcolumn->RemoveAllChildren();
  217. TopicList::Iterator iter(m_listTopic);
  218. while (!iter.End()) {
  219. Topic* ptopic = iter.Value();
  220. if (IsTopicOpen(ptopic)) {
  221. ptopic->SetColor(
  222. IsTopicSelected(ptopic)
  223. ? m_colorSelected
  224. : m_color
  225. );
  226. m_pcolumn->InsertAtBottom(ptopic->GetPane());
  227. }
  228. iter.Next();
  229. }
  230. }
  231. Topic* FindTopic(const ZString& str)
  232. {
  233. TopicList::Iterator iter(m_listTopic);
  234. while (!iter.End()) {
  235. Topic* ptopic = iter.Value();
  236. if (ptopic->m_strMain == str) {
  237. return ptopic;
  238. }
  239. iter.Next();
  240. }
  241. return NULL;
  242. }
  243. //////////////////////////////////////////////////////////////////////////////
  244. //
  245. // NavPane methods
  246. //
  247. //////////////////////////////////////////////////////////////////////////////
  248. void SetTopic(const ZString& str)
  249. {
  250. m_ptopicSelected = FindTopic(str);
  251. UpdatePanes();
  252. }
  253. const ZString& GetSecondary(const ZString& str)
  254. {
  255. Topic* ptopic = FindTopic(str);
  256. if (ptopic) {
  257. return ptopic->m_strSecondary;
  258. } else {
  259. return str;
  260. }
  261. }
  262. virtual TRef<IStringEventSource> GetEventSource()
  263. {
  264. return m_peventSource;
  265. }
  266. //////////////////////////////////////////////////////////////////////////////
  267. //
  268. // Pane methods
  269. //
  270. //////////////////////////////////////////////////////////////////////////////
  271. void UpdateLayout()
  272. {
  273. m_pcolumn->UpdateLayout();
  274. }
  275. };
  276. //////////////////////////////////////////////////////////////////////////////
  277. //
  278. // Factories
  279. //
  280. //////////////////////////////////////////////////////////////////////////////
  281. class NavPaneFactory : public IFunction {
  282. public:
  283. TRef<IObject> Apply(ObjectStack& stack)
  284. {
  285. TRef<IObjectList> plist; CastTo(plist, (IObject*)stack.Pop());
  286. TRef<PointValue> psize; CastTo(psize, (IObject*)stack.Pop());
  287. TRef<ColorValue> pcolor; CastTo(pcolor, (IObject*)stack.Pop());
  288. TRef<ColorValue> pcolorSelected; CastTo(pcolorSelected, (IObject*)stack.Pop());
  289. TRef<ColorValue> pcolorHighlight; CastTo(pcolorHighlight, (IObject*)stack.Pop());
  290. TRef<FontValue> pfont; CastTo(pfont, (IObject*)stack.Pop());
  291. return
  292. new NavPaneImpl(
  293. plist,
  294. psize->GetValue(),
  295. pcolor->GetValue(),
  296. pcolorSelected->GetValue(),
  297. pcolorHighlight->GetValue(),
  298. pfont->GetValue()
  299. );
  300. }
  301. };
  302. void AddNavPaneFactory(
  303. INameSpace* pns
  304. ) {
  305. pns->AddMember("NavPane", new NavPaneFactory());
  306. }