directory_view.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Flexlay - A Generic 2D Game Editor
  2. // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #include <ClanLib/Core/IOData/directory_scanner.h>
  17. #include <ClanLib/Display/display.h>
  18. #include "fonts.hpp"
  19. #include "directory_view.hpp"
  20. class DirectoryViewEntry
  21. {
  22. public:
  23. std::string name;
  24. bool directory;
  25. bool hidden;
  26. };
  27. struct DirectoryViewSorter
  28. {
  29. bool operator()(const DirectoryViewEntry& lhs, const DirectoryViewEntry& rhs)
  30. {
  31. if (lhs.directory > rhs.directory)
  32. return true;
  33. else if (lhs.directory < rhs.directory)
  34. return false;
  35. else
  36. return lhs.name < rhs.name;
  37. }
  38. };
  39. class DirectoryViewImpl
  40. {
  41. public:
  42. DirectoryView* parent;
  43. std::vector<CL_Slot> slots;
  44. std::string path;
  45. CL_Signal_v1<std::string> sig_on_click;
  46. typedef std::vector<DirectoryViewEntry> Items;
  47. Items items;
  48. int current_item;
  49. int column_width;
  50. int num_columns;
  51. void update_items();
  52. void draw();
  53. int get_item(const CL_Point& pos);
  54. void on_mouse_move(const CL_InputEvent& event);
  55. void on_mouse_down(const CL_InputEvent& event);
  56. };
  57. DirectoryView::DirectoryView(const CL_Rect& rect, CL_Component* parent)
  58. : CL_Component(rect, parent),
  59. impl(new DirectoryViewImpl())
  60. {
  61. impl->parent = this;
  62. // impl->slots.push_back(sig_mouse_down().connect(impl.get(), &DirectoryViewImpl::draw));
  63. impl->slots.push_back(sig_paint().connect(impl.get(), &DirectoryViewImpl::draw));
  64. impl->slots.push_back(sig_mouse_move().connect(impl.get(), &DirectoryViewImpl::on_mouse_move));
  65. impl->slots.push_back(sig_mouse_down().connect(impl.get(), &DirectoryViewImpl::on_mouse_down));
  66. impl->current_item = -1;
  67. }
  68. DirectoryView::~DirectoryView()
  69. {
  70. }
  71. void
  72. DirectoryView::set_directory(const std::string& path_)
  73. {
  74. impl->path = path_;
  75. impl->update_items();
  76. }
  77. CL_Signal_v1<std::string>&
  78. DirectoryView::sig_on_click()
  79. {
  80. return impl->sig_on_click;
  81. }
  82. void
  83. DirectoryViewImpl::draw()
  84. {
  85. CL_Font font = Fonts::verdana11;
  86. int horizontal_spacing = 10;
  87. int vertical_spacing = 5;
  88. int x_pos = 0;
  89. int y_pos = 0;
  90. CL_Display::clear(CL_Color(255, 255, 0));
  91. int j = 0;
  92. for(Items::iterator i = items.begin(); i != items.begin()+50 && i != items.end(); ++i)
  93. {
  94. if (current_item && current_item < int(items.size()) && j == current_item)
  95. {
  96. CL_Rect rect = font.bounding_rect(x_pos * (column_width + horizontal_spacing) + 1,
  97. y_pos * (font.get_height() + vertical_spacing) + 1,
  98. i->name);
  99. CL_Display::fill_rect(CL_Rect(rect.left-5, rect.top-3,
  100. rect.left+5+column_width, rect.bottom+3),
  101. CL_Color(250, 200, 0));
  102. }
  103. // draw item
  104. if (!i->directory)
  105. {
  106. font.draw(x_pos * (column_width + horizontal_spacing),
  107. y_pos * (font.get_height() + vertical_spacing),
  108. i->name);
  109. }
  110. else
  111. {
  112. font.draw(x_pos * (column_width + horizontal_spacing),
  113. y_pos * (font.get_height() + vertical_spacing),
  114. "[" + i->name + "]");
  115. }
  116. x_pos += 1;
  117. if (x_pos >= num_columns)
  118. {
  119. x_pos = 0;
  120. y_pos += 1;
  121. }
  122. ++j;
  123. }
  124. }
  125. int
  126. DirectoryViewImpl::get_item(const CL_Point& pos)
  127. {
  128. CL_Font font = Fonts::verdana11;
  129. int horizontal_spacing = 10;
  130. int vertical_spacing = 5;
  131. return (pos.x / (column_width + horizontal_spacing))
  132. + num_columns * (pos.y / (font.get_height() + vertical_spacing));
  133. }
  134. void
  135. DirectoryViewImpl::on_mouse_down(const CL_InputEvent& event)
  136. {
  137. current_item = get_item(event.mouse_pos);
  138. if (current_item >= 0 && current_item < int(items.size()))
  139. {
  140. if (items[current_item].directory)
  141. parent->set_directory(path + "/" + items[current_item].name);
  142. }
  143. }
  144. void
  145. DirectoryViewImpl::on_mouse_move(const CL_InputEvent& event)
  146. {
  147. current_item = get_item(event.mouse_pos);
  148. }
  149. void
  150. DirectoryViewImpl::update_items()
  151. {
  152. items.clear();
  153. CL_DirectoryScanner scanner;
  154. scanner.scan(path);
  155. while(scanner.next())
  156. {
  157. DirectoryViewEntry entry;
  158. entry.name = scanner.get_name();
  159. entry.hidden = (scanner.get_name()[0] == '.');
  160. entry.directory = scanner.is_directory();
  161. items.push_back(entry);
  162. }
  163. std::sort(items.begin(), items.end(), DirectoryViewSorter());
  164. CL_Font font = Fonts::verdana11;
  165. column_width = 60; // min_colum_width
  166. for(Items::iterator i = items.begin(); i != items.end(); ++i)
  167. {
  168. CL_Rect rect = font.bounding_rect(0, 0, i->name + "[]");
  169. column_width = std::max(column_width, rect.get_width());
  170. }
  171. num_columns = parent->get_width()/column_width;
  172. }
  173. /* EOF */