1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "ColorTable.h" 21 22 #include "View/ColorTableSelectedCommand.h" 23 24 #include <wx/dcclient.h> 25 #include <wx/panel.h> 26 #include <wx/sizer.h> 27 28 #include <algorithm> 29 #include <cassert> 30 31 namespace TrenchBroom { 32 namespace View { ColorTable(wxWindow * parent,wxWindowID winId,int cellSize,const wxPoint & pos,const wxSize & size,long style)33 ColorTable::ColorTable(wxWindow* parent, wxWindowID winId, int cellSize, const wxPoint& pos, const wxSize& size, long style) : 34 wxScrolledWindow(parent, winId, pos, size, (style & ~static_cast<long>(wxHSCROLL)) | static_cast<long>(wxVSCROLL)), 35 m_cellSize(cellSize), 36 m_margin(2) { 37 assert(m_cellSize > 0); 38 39 Bind(wxEVT_SIZE, &ColorTable::OnSize, this); 40 Bind(wxEVT_PAINT, &ColorTable::OnPaint, this); 41 Bind(wxEVT_LEFT_UP, &ColorTable::OnMouseUp, this); 42 43 SetScrollRate(0, m_cellSize + m_margin); 44 } 45 setColors(const ColorList & colors)46 void ColorTable::setColors(const ColorList& colors) { 47 m_colors = colors; 48 m_selectedColors.clear(); 49 updateVirtualSize(); 50 } 51 setSelection(const ColorList & colors)52 void ColorTable::setSelection(const ColorList& colors) { 53 m_selectedColors = colors; 54 Refresh(); 55 } 56 OnSize(wxSizeEvent & event)57 void ColorTable::OnSize(wxSizeEvent& event) { 58 if (IsBeingDeleted()) return; 59 60 updateVirtualSize(); 61 } 62 OnPaint(wxPaintEvent & event)63 void ColorTable::OnPaint(wxPaintEvent& event) { 64 if (IsBeingDeleted()) return; 65 66 const wxSize virtualSize = GetVirtualSize(); 67 const int cols = computeCols(virtualSize.x); 68 const int rows = computeRows(cols); 69 70 const wxPoint viewStart = GetViewStart(); 71 int xRate, yRate; 72 GetScrollPixelsPerUnit(&xRate, &yRate); 73 74 const int startX = -(viewStart.x * xRate) + m_margin; 75 int x = startX; 76 int y = -(viewStart.y * yRate) + m_margin; 77 78 wxPaintDC dc(this); 79 dc.SetPen(*wxTRANSPARENT_PEN); 80 dc.SetBrush(*wxWHITE_BRUSH); 81 dc.DrawRectangle(0, 0, virtualSize.x, virtualSize.y); 82 83 ColorList::const_iterator it = m_colors.begin(); 84 for (int row = 0; row < rows; ++row) { 85 for (int col = 0; col < cols; ++col) { 86 if (it != m_colors.end()) { 87 const wxColour& color = *it; 88 89 if (std::find(m_selectedColors.begin(), m_selectedColors.end(), color) != m_selectedColors.end()) { 90 dc.SetPen(*wxRED_PEN); 91 dc.SetBrush(*wxRED_BRUSH); 92 dc.DrawRectangle(x-1, y-1, m_cellSize+2, m_cellSize+2); 93 } 94 95 dc.SetPen(wxPen(color)); 96 dc.SetBrush(wxBrush(color)); 97 dc.DrawRectangle(x, y, m_cellSize, m_cellSize); 98 99 ++it; 100 } 101 x += m_cellSize + m_margin; 102 } 103 y += m_cellSize + m_margin; 104 x = startX; 105 } 106 } 107 OnMouseUp(wxMouseEvent & event)108 void ColorTable::OnMouseUp(wxMouseEvent& event) { 109 if (IsBeingDeleted()) return; 110 111 const wxSize virtualSize = GetVirtualSize(); 112 const int cols = computeCols(virtualSize.x); 113 114 const wxPoint pos = CalcScrolledPosition(event.GetPosition()); 115 const int col = (pos.x - m_margin) / (m_cellSize + m_margin); 116 const int row = (pos.y - m_margin) / (m_cellSize + m_margin); 117 118 const size_t index = static_cast<size_t>(row * cols + col); 119 if (index < m_colors.size()) { 120 const wxColor& color = m_colors[index]; 121 122 ColorTableSelectedCommand command; 123 command.setColor(color); 124 command.SetEventObject(this); 125 command.SetId(GetId()); 126 ProcessEvent(command); 127 } 128 } 129 updateVirtualSize()130 void ColorTable::updateVirtualSize() { 131 int width = GetClientSize().x; 132 int cols = computeCols(width); 133 int rows = computeRows(cols); 134 int height = computeHeight(rows); 135 SetVirtualSize(width, height); 136 137 if (GetClientSize().x != width) { 138 width = GetClientSize().x; 139 cols = computeCols(width); 140 rows = computeRows(cols); 141 height = computeHeight(rows); 142 SetVirtualSize(width, height); 143 assert(width == GetClientSize().x); 144 } 145 } 146 computeCols(const int width) const147 int ColorTable::computeCols(const int width) const { 148 return (width - m_margin) / (m_cellSize + m_margin); 149 } 150 computeRows(const int cols) const151 int ColorTable::computeRows(const int cols) const { 152 if (cols == 0) 153 return 0; 154 return (static_cast<int>(m_colors.size()) + cols - 1) / cols; 155 } 156 computeHeight(const int rows) const157 int ColorTable::computeHeight(const int rows) const { 158 return m_margin + rows * (m_cellSize + m_margin) - 1; // no idea why the -1 is necessary, but it is 159 } 160 } 161 } 162