Changeset 18333 in webkit
- Timestamp:
- Dec 19, 2006 5:49:03 PM (17 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r18332 r18333 1 2006-12-19 Darin Adler <darin@apple.com> 2 3 Reviewed by Geoff. 4 5 - <rdar://problem/4885227> 6 frame resizing is now live and no longer does direct drawing 7 8 * html/HTMLFrameSetElement.h: Made frameBorder() and noResize() const. 9 Added rowLengths() and colLengths() getters so that we don't have to 10 have RenderFrameSet as a friend. Stopped using bit fields. 11 12 * html/HTMLFrameSetElement.cpp: 13 (WebCore::HTMLFrameSetElement::defaultEventHandler): Removed now-uneeded 14 check for contextmenu events. Look at return value from userResize to 15 decide whether to mark the event as "default handled". In the case where 16 the event is handled, don't call through to the base class. 17 18 * rendering/RenderFrameSet.h: No longer mark HTMLFrameSetElement as a 19 friend. Made positionFrames and canResize private, and changed canResize 20 to take an IntPoint. Added isResizingRow, isResizingColumn, canResizeRow, 21 and canResizeColumn functions to be used soon for cursor feedback. 22 Removed override of non-virtual element() function and replaced it with 23 a private frameSet() inline function. Grouped all the data members for 24 each axis into a GridAxis class, and made one called m_cols and one called 25 m_rows. Used vectors for the resizable bits of this instead of new/delete 26 arrays. Added a constant named "noSplit" so we don't have to use -1 27 everywhere explicitly for this purpose. Renamed setResizing to 28 setIsResizing and made it private. Eliminated resizing() function. 29 Added new private helper functions, layOutAxis, findNonResizableSplits, 30 splitPosition, hitTestSplit, startResizing, and continueResizing. 31 Renamed m_resizing to m_isResizing, and m_clientResizing to 32 m_isChildResizing. 33 34 * rendering/RenderFrameSet.cpp: 35 (WebCore::RenderFrameSet::RenderFrameSet): Removed now-unneeded initialization 36 that is handled by the GridAxis and Vector constructors. 37 (WebCore::RenderFrameSet::~RenderFrameSet): Ditto (for destructors). 38 (WebCore::RenderFrameSet::GridAxis::GridAxis): Added. 39 (WebCore::RenderFrameSet::frameSet): Added. Inline function so we don't have 40 to cast the result of node() or element() everywhere. 41 (WebCore::RenderFrameSet::nodeAtPoint): Updated for name changes. 42 (WebCore::RenderFrameSet::GridAxis::resize): Added. Helper function to be used 43 in the layout function. 44 (WebCore::RenderFrameSet::layOutAxis): Added. Factored out the part of the 45 layout function that used to be inside a for loop for the two axes. 46 The algorithm is otherwise unchanged. 47 (WebCore::RenderFrameSet::findNonResizableSplits): Added. Factored out the 48 code that set up the "split variable" arrays from the layout function. 49 (WebCore::RenderFrameSet::layout): Moved the bulk of this function into the 50 new helpers. This allowed me to remove the use of goto. 51 (WebCore::RenderFrameSet::positionFrames): Updated for change to data structures. 52 Also added some more local variables for clarity. 53 (WebCore::RenderFrameSet::startResizing): Added. Code factored out of the 54 userResize function that handles mousedown events that might begin a resize. 55 (WebCore::RenderFrameSet::continueResizing): Added. Code factored out of the 56 userResize function that handles mouse events that continue a resize already 57 in progress, including mouseup events that end the resizing. Uses the new 58 splitPosition function so it can be used over and over again while resizing. 59 (WebCore::RenderFrameSet::userResize): Restructured to use the new helper 60 functions. Removed the direct drawing of a gray bar during mouse movement; 61 instead we do the resizing live. 62 (WebCore::RenderFrameSet::setIsResizing): Updated for name changes. 63 (WebCore::RenderFrameSet::isResizingRow): Added. 64 (WebCore::RenderFrameSet::isResizingColumn): Added. 65 (WebCore::RenderFrameSet::canResize): Changed to use hitTestSplit for clarity. 66 (WebCore::RenderFrameSet::canResizeRow): Added. 67 (WebCore::RenderFrameSet::canResizeColumn): Added. 68 (WebCore::RenderFrameSet::splitPosition): Added. 69 (WebCore::RenderFrameSet::hitTestSplit): Added. Contains the guts of the code 70 that was used both in canResize and userResize before -- now it's shared. 71 (WebCore::RenderFrameSet::dump): Updated for name changes. 72 1 73 2006-12-19 Justin Garcia <justin.garcia@apple.com> 2 74 -
trunk/WebCore/html/HTMLFrameSetElement.cpp
r18072 r18333 139 139 void HTMLFrameSetElement::defaultEventHandler(Event* evt) 140 140 { 141 if (evt->isMouseEvent() && evt->type() != contextmenuEvent && !noresize && renderer()) {142 static_cast<RenderFrameSet*>(renderer())->userResize(static_cast<MouseEvent*>(evt));143 evt->setDefaultHandled();144 }145 141 if (evt->isMouseEvent() && !noresize && renderer()) 142 if (static_cast<RenderFrameSet*>(renderer())->userResize(static_cast<MouseEvent*>(evt))) { 143 evt->setDefaultHandled(); 144 return; 145 } 146 146 HTMLElement::defaultEventHandler(evt); 147 147 } -
trunk/WebCore/html/HTMLFrameSetElement.h
r14334 r18333 31 31 namespace WebCore { 32 32 33 class HTMLFrameSetElement : public HTMLElement 34 { 35 friend class RenderFrameSet; 33 class HTMLFrameSetElement : public HTMLElement { 36 34 public: 37 35 HTMLFrameSetElement(Document*); … … 49 47 virtual void defaultEventHandler(Event*); 50 48 51 bool frameBorder() { return frameborder; }52 bool noResize() { return noresize; }49 bool frameBorder() const { return frameborder; } 50 bool noResize() const { return noresize; } 53 51 54 52 int totalRows() const { return m_totalRows; } … … 64 62 void setRows(const String&); 65 63 66 protected: 64 const Length* rowLengths() const { return m_rows; } 65 const Length* colLengths() const { return m_cols; } 66 67 private: 67 68 Length* m_rows; 68 69 Length* m_cols; … … 72 73 int m_border; 73 74 74 bool frameborder : 1;75 bool frameBorderSet : 1;76 bool noresize : 1;75 bool frameborder; 76 bool frameBorderSet; 77 bool noresize; 77 78 }; 78 79 -
trunk/WebCore/rendering/RenderFrameSet.cpp
r18294 r18333 27 27 #include "RenderFrameSet.h" 28 28 29 #include "Cursor.h"30 29 #include "Document.h" 31 30 #include "EventHandler.h" … … 33 32 #include "Frame.h" 34 33 #include "FrameView.h" 35 #include "GraphicsContext.h"36 34 #include "HTMLFrameSetElement.h" 37 #include "HTMLNames.h"38 35 #include "HitTestRequest.h" 39 36 #include "HitTestResult.h" … … 46 43 47 44 using namespace EventNames; 48 using namespace HTMLNames;49 45 50 46 RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet) 51 47 : RenderContainer(frameSet) 52 , m_hSplitVar(0) 53 , m_vSplitVar(0) 54 , m_hSplit(-1) 55 , m_vSplit(-1) 56 , m_resizing(false) 57 , m_clientResizing(false) 58 { 59 // init RenderObject attributes 48 , m_isResizing(false) 49 , m_isChildResizing(false) 50 { 60 51 setInline(false); 61 62 for (int k = 0; k < 2; ++k) {63 m_gridLen[k] = -1;64 m_gridDelta[k] = 0;65 m_gridLayout[k] = 0;66 }67 52 } 68 53 69 54 RenderFrameSet::~RenderFrameSet() 70 55 { 71 for (int k = 0; k < 2; ++k) { 72 if (m_gridLayout[k]) 73 delete [] m_gridLayout[k]; 74 if (m_gridDelta[k])75 delete [] m_gridDelta[k]; 76 77 if (m_hSplitVar) 78 delete [] m_hSplitVar; 79 if (m_vSplitVar) 80 delete [] m_vSplitVar;56 } 57 58 RenderFrameSet::GridAxis::GridAxis() 59 : m_splitBeingResized(noSplit) 60 { 61 } 62 63 inline HTMLFrameSetElement* RenderFrameSet::frameSet() const 64 { 65 return static_cast<HTMLFrameSetElement*>(node()); 81 66 } 82 67 83 68 bool RenderFrameSet::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, 84 int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)85 { 86 if ( hitTestAction != HitTestForeground)69 int x, int y, int tx, int ty, HitTestAction action) 70 { 71 if (action != HitTestForeground) 87 72 return false; 88 73 89 bool inside = RenderContainer::nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction) || 90 m_resizing || canResize(_x, _y); 91 if (inside && element() && !element()->noResize() && !request.readonly && !result.innerNode()) { 92 result.setInnerNode(element()); 93 result.setInnerNonSharedNode(element()); 94 } 95 96 return inside || m_clientResizing; 74 bool inside = RenderContainer::nodeAtPoint(request, result, x, y, tx, ty, action) 75 || m_isResizing || canResize(IntPoint(x, y)); 76 77 if (inside && frameSet()->noResize() 78 && !request.readonly && !result.innerNode()) { 79 result.setInnerNode(node()); 80 result.setInnerNonSharedNode(node()); 81 } 82 83 return inside || m_isChildResizing; 84 } 85 86 void RenderFrameSet::GridAxis::resize(int size) 87 { 88 m_sizes.resize(size); 89 m_deltas.resize(size); 90 m_deltas.fill(0); 91 m_isSplitResizable.resize(size); 92 } 93 94 void RenderFrameSet::layOutAxis(GridAxis& axis, const Length* grid, int availableLen) 95 { 96 int* gridLayout = axis.m_sizes; 97 98 if (!grid) { 99 gridLayout[0] = availableLen; 100 return; 101 } 102 103 int gridLen = axis.m_sizes.size(); 104 ASSERT(gridLen); 105 106 int totalRelative = 0; 107 int totalFixed = 0; 108 int totalPercent = 0; 109 int countRelative = 0; 110 int countFixed = 0; 111 int countPercent = 0; 112 113 // First we need to investigate how many columns of each type we have and 114 // how much space these columns are going to require. 115 for (int i = 0; i < gridLen; ++i) { 116 // Count the total length of all of the fixed columns/rows -> totalFixed 117 // Count the number of columns/rows which are fixed -> countFixed 118 if (grid[i].isFixed()) { 119 gridLayout[i] = max(grid[i].value(), 0); 120 totalFixed += gridLayout[i]; 121 countFixed++; 122 } 123 124 // Count the total percentage of all of the percentage columns/rows -> totalPercent 125 // Count the number of columns/rows which are percentages -> countPercent 126 if (grid[i].isPercent()) { 127 gridLayout[i] = max(grid[i].calcValue(availableLen), 0); 128 totalPercent += gridLayout[i]; 129 countPercent++; 130 } 131 132 // Count the total relative of all the relative columns/rows -> totalRelative 133 // Count the number of columns/rows which are relative -> countRelative 134 if (grid[i].isRelative()) { 135 totalRelative += max(grid[i].value(), 1); 136 countRelative++; 137 } 138 } 139 140 int remainingLen = availableLen; 141 142 // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed 143 // columns/rows we need to proportionally adjust their size. 144 if (totalFixed > remainingLen) { 145 int remainingFixed = remainingLen; 146 147 for (int i = 0; i < gridLen; ++i) { 148 if (grid[i].isFixed()) { 149 gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed; 150 remainingLen -= gridLayout[i]; 151 } 152 } 153 } else 154 remainingLen -= totalFixed; 155 156 // Percentage columns/rows are our second priority. Divide the remaining space proportionally 157 // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative 158 // to 100%, but to the total percentage. For example, if there are three columns, each of 75%, 159 // and the available space is 300px, each column will become 100px in width. 160 if (totalPercent > remainingLen) { 161 int remainingPercent = remainingLen; 162 163 for (int i = 0; i < gridLen; ++i) { 164 if (grid[i].isPercent()) { 165 gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent; 166 remainingLen -= gridLayout[i]; 167 } 168 } 169 } else 170 remainingLen -= totalPercent; 171 172 // Relative columns/rows are our last priority. Divide the remaining space proportionally 173 // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*. 174 if (countRelative) { 175 int lastRelative = 0; 176 int remainingRelative = remainingLen; 177 178 for (int i = 0; i < gridLen; ++i) { 179 if (grid[i].isRelative()) { 180 gridLayout[i] = (max(grid[i].value(), 1) * remainingRelative) / totalRelative; 181 remainingLen -= gridLayout[i]; 182 lastRelative = i; 183 } 184 } 185 186 // If we could not evenly distribute the available space of all of the relative 187 // columns/rows, the remainder will be added to the last column/row. 188 // For example: if we have a space of 100px and three columns (*,*,*), the remainder will 189 // be 1px and will be added to the last column: 33px, 33px, 34px. 190 if (remainingLen) { 191 gridLayout[lastRelative] += remainingLen; 192 remainingLen = 0; 193 } 194 } 195 196 // If we still have some left over space we need to divide it over the already existing 197 // columns/rows 198 if (remainingLen) { 199 // Our first priority is to spread if over the percentage columns. The remaining 200 // space is spread evenly, for example: if we have a space of 100px, the columns 201 // definition of 25%,25% used to result in two columns of 25px. After this the 202 // columns will each be 50px in width. 203 if (countPercent && totalPercent) { 204 int remainingPercent = remainingLen; 205 int changePercent = 0; 206 207 for (int i = 0; i < gridLen; ++i) { 208 if (grid[i].isPercent()) { 209 changePercent = (remainingPercent * gridLayout[i]) / totalPercent; 210 gridLayout[i] += changePercent; 211 remainingLen -= changePercent; 212 } 213 } 214 } else if (totalFixed) { 215 // Our last priority is to spread the remaining space over the fixed columns. 216 // For example if we have 100px of space and two column of each 40px, both 217 // columns will become exactly 50px. 218 int remainingFixed = remainingLen; 219 int changeFixed = 0; 220 221 for (int i = 0; i < gridLen; ++i) { 222 if (grid[i].isFixed()) { 223 changeFixed = (remainingFixed * gridLayout[i]) / totalFixed; 224 gridLayout[i] += changeFixed; 225 remainingLen -= changeFixed; 226 } 227 } 228 } 229 } 230 231 // If we still have some left over space we probably ended up with a remainder of 232 // a division. We can not spread it evenly anymore. If we have any percentage 233 // columns/rows simply spread the remainder equally over all available percentage columns, 234 // regardless of their size. 235 if (remainingLen && countPercent) { 236 int remainingPercent = remainingLen; 237 int changePercent = 0; 238 239 for (int i = 0; i < gridLen; ++i) { 240 if (grid[i].isPercent()) { 241 changePercent = remainingPercent / countPercent; 242 gridLayout[i] += changePercent; 243 remainingLen -= changePercent; 244 } 245 } 246 } 247 248 // If we don't have any percentage columns/rows we only have fixed columns. Spread 249 // the remainder equally over all fixed columns/rows. 250 else if (remainingLen && countFixed) { 251 int remainingFixed = remainingLen; 252 int changeFixed = 0; 253 254 for (int i = 0; i < gridLen; ++i) { 255 if (grid[i].isFixed()) { 256 changeFixed = remainingFixed / countFixed; 257 gridLayout[i] += changeFixed; 258 remainingLen -= changeFixed; 259 } 260 } 261 } 262 263 // Still some left over. Add it to the last column, because it is impossible 264 // spread it evenly or equally. 265 if (remainingLen) 266 gridLayout[gridLen - 1] += remainingLen; 267 268 // now we have the final layout, distribute the delta over it 269 bool worked = true; 270 int* gridDelta = axis.m_deltas; 271 for (int i = 0; i < gridLen; ++i) { 272 if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0) 273 worked = false; 274 gridLayout[i] += gridDelta[i]; 275 } 276 // if the deltas broke something, undo them 277 if (!worked) { 278 for (int i = 0; i < gridLen; ++i) 279 gridLayout[i] -= gridDelta[i]; 280 axis.m_deltas.fill(0); 281 } 282 } 283 284 void RenderFrameSet::findNonResizableSplits() 285 { 286 m_rows.m_isSplitResizable.fill(true); 287 m_cols.m_isSplitResizable.fill(true); 288 289 RenderObject* child = firstChild(); 290 if (!child) 291 return; 292 293 int rows = frameSet()->totalRows(); 294 int cols = frameSet()->totalCols(); 295 for (int r = 0; r < rows; ++r) { 296 for (int c = 0; c < cols; ++c) { 297 bool fixed; 298 if (child->isFrameSet()) 299 fixed = static_cast<RenderFrameSet*>(child)->frameSet()->noResize(); 300 else 301 fixed = static_cast<RenderFrame*>(child)->element()->noResize(); 302 if (fixed) { 303 if (cols > 1) { 304 if (c > 0) 305 m_cols.m_isSplitResizable[c - 1] = false; 306 m_cols.m_isSplitResizable[c] = false; 307 } 308 if (rows > 1) { 309 if (r > 0) 310 m_rows.m_isSplitResizable[r - 1] = false; 311 m_rows.m_isSplitResizable[r] = false; 312 } 313 } 314 child = child->nextSibling(); 315 if (!child) 316 return; 317 } 318 } 97 319 } 98 320 … … 108 330 } 109 331 110 int remainingLen[2]; 111 remainingLen[1] = m_width - (element()->totalCols()-1)*element()->border(); 112 if (remainingLen[1] < 0) 113 remainingLen[1] = 0; 114 remainingLen[0] = m_height - (element()->totalRows()-1)*element()->border(); 115 if (remainingLen[0] < 0) 116 remainingLen[0] = 0; 117 118 int availableLen[2]; 119 availableLen[0] = remainingLen[0]; 120 availableLen[1] = remainingLen[1]; 121 122 if (m_gridLen[0] != element()->totalRows() || m_gridLen[1] != element()->totalCols()) { 123 // number of rows or cols changed 124 // need to zero out the deltas 125 m_gridLen[0] = element()->totalRows(); 126 m_gridLen[1] = element()->totalCols(); 127 for (int k = 0; k < 2; ++k) { 128 if (m_gridDelta[k]) delete [] m_gridDelta[k]; 129 m_gridDelta[k] = new int[m_gridLen[k]]; 130 if (m_gridLayout[k]) delete [] m_gridLayout[k]; 131 m_gridLayout[k] = new int[m_gridLen[k]]; 132 for (int i = 0; i < m_gridLen[k]; ++i) 133 m_gridDelta[k][i] = 0; 134 } 135 } 136 137 for (int k = 0; k < 2; ++k) { 138 int totalRelative = 0; 139 int totalFixed = 0; 140 int totalPercent = 0; 141 int countRelative = 0; 142 int countFixed = 0; 143 int countPercent = 0; 144 int gridLen = m_gridLen[k]; 145 int* gridDelta = m_gridDelta[k]; 146 Length* grid = k ? element()->m_cols : element()->m_rows; 147 int* gridLayout = m_gridLayout[k]; 148 149 if (grid) { 150 assert(gridLen); 151 // First we need to investigate how many columns of each type we have and 152 // how much space these columns are going to require. 153 for (int i = 0; i < gridLen; ++i) { 154 // Count the total length of all of the fixed columns/rows -> totalFixed 155 // Count the number of columns/rows which are fixed -> countFixed 156 if (grid[i].isFixed()) { 157 gridLayout[i] = max(grid[i].value(), 0); 158 totalFixed += gridLayout[i]; 159 countFixed++; 160 } 161 162 // Count the total percentage of all of the percentage columns/rows -> totalPercent 163 // Count the number of columns/rows which are percentages -> countPercent 164 if (grid[i].isPercent()) { 165 gridLayout[i] = max(grid[i].calcValue(availableLen[k]), 0); 166 totalPercent += gridLayout[i]; 167 countPercent++; 168 } 169 170 // Count the total relative of all the relative columns/rows -> totalRelative 171 // Count the number of columns/rows which are relative -> countRelative 172 if (grid[i].isRelative()) { 173 totalRelative += max(grid[i].value(), 1); 174 countRelative++; 175 } 176 } 177 178 // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed 179 // columns/rows we need to proportionally adjust their size. 180 if (totalFixed > remainingLen[k]) { 181 int remainingFixed = remainingLen[k]; 182 183 for (int i = 0; i < gridLen; ++i) { 184 if (grid[i].isFixed()) { 185 gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed; 186 remainingLen[k] -= gridLayout[i]; 187 } 188 } 189 } else 190 remainingLen[k] -= totalFixed; 191 192 // Percentage columns/rows are our second priority. Divide the remaining space proportionally 193 // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative 194 // to 100%, but to the total percentage. For example, if there are three columns, each of 75%, 195 // and the available space is 300px, each column will become 100px in width. 196 if (totalPercent > remainingLen[k]) { 197 int remainingPercent = remainingLen[k]; 198 199 for (int i = 0; i < gridLen; ++i) { 200 if (grid[i].isPercent()) { 201 gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent; 202 remainingLen[k] -= gridLayout[i]; 203 } 204 } 205 } else 206 remainingLen[k] -= totalPercent; 207 208 // Relative columns/rows are our last priority. Divide the remaining space proportionally 209 // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*. 210 if (countRelative) { 211 int lastRelative = 0; 212 int remainingRelative = remainingLen[k]; 213 214 for (int i = 0; i < gridLen; ++i) { 215 if (grid[i].isRelative()) { 216 gridLayout[i] = (max(grid[i].value(), 1) * remainingRelative) / totalRelative; 217 remainingLen[k] -= gridLayout[i]; 218 lastRelative = i; 219 } 220 } 221 222 // If we could not evently distribute the available space of all of the relative 223 // columns/rows, the remainder will be added to the last column/row. 224 // For example: if we have a space of 100px and three columns (*,*,*), the remainder will 225 // be 1px and will be added to the last column: 33px, 33px, 34px. 226 if (remainingLen[k]) { 227 gridLayout[lastRelative] += remainingLen[k]; 228 remainingLen[k] = 0; 229 } 230 } 231 232 // If we still have some left over space we need to divide it over the already existing 233 // columns/rows 234 if (remainingLen[k]) { 235 // Our first priority is to spread if over the percentage columns. The remaining 236 // space is spread evenly, for example: if we have a space of 100px, the columns 237 // definition of 25%,25% used to result in two columns of 25px. After this the 238 // columns will each be 50px in width. 239 if (countPercent && totalPercent) { 240 int remainingPercent = remainingLen[k]; 241 int changePercent = 0; 242 243 for (int i = 0; i < gridLen; ++i) { 244 if (grid[i].isPercent()) { 245 changePercent = (remainingPercent * gridLayout[i]) / totalPercent; 246 gridLayout[i] += changePercent; 247 remainingLen[k] -= changePercent; 248 } 249 } 250 } else if (totalFixed) { 251 // Our last priority is to spread the remaining space over the fixed columns. 252 // For example if we have 100px of space and two column of each 40px, both 253 // columns will become exactly 50px. 254 int remainingFixed = remainingLen[k]; 255 int changeFixed = 0; 256 257 for (int i = 0; i < gridLen; ++i) { 258 if (grid[i].isFixed()) { 259 changeFixed = (remainingFixed * gridLayout[i]) / totalFixed; 260 gridLayout[i] += changeFixed; 261 remainingLen[k] -= changeFixed; 262 } 263 } 264 } 265 } 266 267 // If we still have some left over space we probably ended up with a remainder of 268 // a division. We can not spread it evenly anymore. If we have any percentage 269 // columns/rows simply spread the remainder equally over all available percentage columns, 270 // regardless of their size. 271 if (remainingLen[k] && countPercent) { 272 int remainingPercent = remainingLen[k]; 273 int changePercent = 0; 274 275 for (int i = 0; i < gridLen; ++i) { 276 if (grid[i].isPercent()) { 277 changePercent = remainingPercent / countPercent; 278 gridLayout[i] += changePercent; 279 remainingLen[k] -= changePercent; 280 } 281 } 282 } 283 284 // If we don't have any percentage columns/rows we only have fixed columns. Spread 285 // the remainder equally over all fixed columns/rows. 286 else if (remainingLen[k] && countFixed) { 287 int remainingFixed = remainingLen[k]; 288 int changeFixed = 0; 289 290 for (int i = 0; i < gridLen; ++i) { 291 if (grid[i].isFixed()) { 292 changeFixed = remainingFixed / countFixed; 293 gridLayout[i] += changeFixed; 294 remainingLen[k] -= changeFixed; 295 } 296 } 297 } 298 299 // Still some left over... simply add it to the last column, because it is impossible 300 // spread it evenly or equally. 301 if (remainingLen[k]) 302 gridLayout[gridLen - 1] += remainingLen[k]; 303 304 // now we have the final layout, distribute the delta over it 305 bool worked = true; 306 for (int i = 0; i < gridLen; ++i) { 307 if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0) 308 worked = false; 309 gridLayout[i] += gridDelta[i]; 310 } 311 // now the delta's broke something, undo it and reset deltas 312 if (!worked) { 313 for (int i = 0; i < gridLen; ++i) { 314 gridLayout[i] -= gridDelta[i]; 315 gridDelta[i] = 0; 316 } 317 } 318 } 319 else 320 gridLayout[0] = remainingLen[k]; 321 } 332 size_t cols = frameSet()->totalCols(); 333 size_t rows = frameSet()->totalRows(); 334 335 if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) { 336 m_rows.resize(rows); 337 m_cols.resize(cols); 338 findNonResizableSplits(); 339 } 340 341 int borderThickness = frameSet()->border(); 342 layOutAxis(m_rows, frameSet()->rowLengths(), m_height - (rows - 1) * borderThickness); 343 layOutAxis(m_cols, frameSet()->colLengths(), m_width - (cols - 1) * borderThickness); 322 344 323 345 positionFrames(); 324 346 325 RenderObject *child = firstChild(); 347 RenderContainer::layout(); 348 349 setNeedsLayout(false); 350 } 351 352 void RenderFrameSet::positionFrames() 353 { 354 RenderObject* child = firstChild(); 326 355 if (!child) 327 goto end2;328 329 if (!m_hSplitVar && !m_vSplitVar) {330 if (!m_vSplitVar && element()->totalCols() > 1) {331 m_vSplitVar = new bool[element()->totalCols()];332 for (int i = 0; i < element()->totalCols(); i++) m_vSplitVar[i] = true;333 }334 if (!m_hSplitVar && element()->totalRows() > 1) {335 m_hSplitVar = new bool[element()->totalRows()];336 for (int i = 0; i < element()->totalRows(); i++) m_hSplitVar[i] = true;337 }338 339 for (int r = 0; r < element()->totalRows(); r++) {340 for (int c = 0; c < element()->totalCols(); c++) {341 bool fixed = false;342 343 if (child->isFrameSet())344 fixed = static_cast<RenderFrameSet*>(child)->element()->noResize();345 else346 fixed = static_cast<RenderFrame*>(child)->element()->noResize();347 348 if (fixed) {349 if (element()->totalCols() > 1) {350 if (c>0) m_vSplitVar[c-1] = false;351 m_vSplitVar[c] = false;352 }353 if (element()->totalRows() > 1) {354 if (r>0) m_hSplitVar[r-1] = false;355 m_hSplitVar[r] = false;356 }357 child = child->nextSibling();358 if (!child)359 goto end1;360 }361 }362 }363 364 }365 end1:366 RenderContainer::layout();367 end2:368 setNeedsLayout(false);369 }370 371 void RenderFrameSet::positionFrames()372 {373 int r;374 int c;375 376 RenderObject *child = firstChild();377 if (!child)378 return;379 380 // Node *child = _first;381 // if (!child) return;382 383 int yPos = 0;384 385 for (r = 0; r < element()->totalRows(); r++) {386 int xPos = 0;387 for (c = 0; c < element()->totalCols(); c++) {388 child->setPos(xPos, yPos);389 // has to be resized and itself resize its contents390 if ((m_gridLayout[1][c] != child->width()) || (m_gridLayout[0][r] != child->height())) {391 child->setWidth(m_gridLayout[1][c]);392 child->setHeight(m_gridLayout[0][r]);393 child->setNeedsLayout(true);394 child->layout();395 }396 397 xPos += m_gridLayout[1][c] + element()->border();398 child = child->nextSibling();399 400 if (!child)401 356 return; 402 357 403 } 404 405 yPos += m_gridLayout[0][r] + element()->border(); 406 } 407 408 // all the remaining frames are hidden to avoid ugly 409 // spurious unflowed frames 410 while (child) { 411 child->setWidth(0); 412 child->setHeight(0); 413 child->setNeedsLayout(false); 414 415 child = child->nextSibling(); 416 } 358 int rows = frameSet()->totalRows(); 359 int cols = frameSet()->totalCols(); 360 361 int yPos = 0; 362 int borderThickness = frameSet()->border(); 363 for (int r = 0; r < rows; r++) { 364 int xPos = 0; 365 int height = m_rows.m_sizes[r]; 366 for (int c = 0; c < cols; c++) { 367 child->setPos(xPos, yPos); 368 int width = m_cols.m_sizes[c]; 369 370 // has to be resized and itself resize its contents 371 if (width != child->width() || height != child->height()) { 372 child->setWidth(width); 373 child->setHeight(height); 374 child->setNeedsLayout(true); 375 child->layout(); 376 } 377 378 xPos += width + borderThickness; 379 380 child = child->nextSibling(); 381 if (!child) 382 return; 383 } 384 yPos += height + borderThickness; 385 } 386 387 // all the remaining frames are hidden to avoid ugly spurious unflowed frames 388 for (; child; child = child->nextSibling()) { 389 child->setWidth(0); 390 child->setHeight(0); 391 child->setNeedsLayout(false); 392 } 393 } 394 395 void RenderFrameSet::startResizing(GridAxis& axis, int position) 396 { 397 int split = hitTestSplit(axis, position); 398 if (split == noSplit || !axis.m_isSplitResizable[split]) { 399 axis.m_splitBeingResized = noSplit; 400 return; 401 } 402 axis.m_splitBeingResized = split; 403 axis.m_splitResizeOffset = position - splitPosition(axis, split); 404 } 405 406 void RenderFrameSet::continueResizing(GridAxis& axis, int position) 407 { 408 if (needsLayout()) 409 return; 410 if (axis.m_splitBeingResized == noSplit) 411 return; 412 int currentSplitPosition = splitPosition(axis, axis.m_splitBeingResized); 413 int delta = (position - currentSplitPosition) - axis.m_splitResizeOffset; 414 axis.m_deltas[axis.m_splitBeingResized] += delta; 415 axis.m_deltas[axis.m_splitBeingResized + 1] -= delta; 416 setNeedsLayout(true); 417 417 } 418 418 … … 422 422 return false; 423 423 424 bool res = false; 425 int _x = evt->pageX(); 426 int _y = evt->pageY(); 427 428 if (!m_resizing && evt->type() == mousemoveEvent || evt->type() == mousedownEvent) { 429 m_hSplit = -1; 430 m_vSplit = -1; 431 //bool resizePossible = true; 432 433 // check if we're over a horizontal or vertical boundary 434 int pos = m_gridLayout[1][0] + xPos(); 435 for (int c = 1; c < element()->totalCols(); c++) { 436 if (_x >= pos && _x <= pos+element()->border()) { 437 if (m_vSplitVar && m_vSplitVar[c - 1]) 438 m_vSplit = c - 1; 439 res = true; 440 break; 441 } 442 pos += m_gridLayout[1][c] + element()->border(); 443 } 444 445 pos = m_gridLayout[0][0] + yPos(); 446 for (int r = 1; r < element()->totalRows(); r++) { 447 if (_y >= pos && _y <= pos+element()->border()) { 448 if (m_hSplitVar && m_hSplitVar[r - 1]) 449 m_hSplit = r - 1; 450 res = true; 451 break; 452 } 453 pos += m_gridLayout[0][r] + element()->border(); 454 } 455 424 if (!m_isResizing) { 456 425 if (evt->type() == mousedownEvent) { 457 setResizing(true); 458 m_vSplitPos = _x; 459 m_hSplitPos = _y; 460 m_oldpos = -1; 461 } 462 } 463 464 // ### check the resize is not going out of bounds. 465 if (m_resizing && evt->type() == mouseupEvent) { 466 setResizing(false); 467 468 if (m_vSplit != -1) { 469 int delta = m_vSplitPos - _x; 470 m_gridDelta[1][m_vSplit] -= delta; 471 m_gridDelta[1][m_vSplit+1] += delta; 472 } 473 if (m_hSplit != -1) { 474 int delta = m_hSplitPos - _y; 475 m_gridDelta[0][m_hSplit] -= delta; 476 m_gridDelta[0][m_hSplit+1] += delta; 477 } 478 479 // this just schedules the relayout 480 // important, otherwise the moving indicator is not correctly erased 481 setNeedsLayout(true); 482 } else if (m_resizing || evt->type() == mouseupEvent) { 483 FrameView* v = view()->frameView(); 484 v->disableFlushDrawing(); 485 GraphicsContext* context = v->lockDrawingFocus(); 486 487 IntRect r(xPos(), yPos(), width(), height()); 488 const int rBord = 3; 489 int sw = element()->border(); 490 int p = m_resizing ? (m_vSplit > -1 ? _x : _y) : -1; 491 const RGBA32 greyQuarterOpacity = 0x40A0A0A0; 492 if (m_vSplit > -1) { 493 if (m_oldpos >= 0) 494 v->updateContents(IntRect(m_oldpos + sw/2 - rBord, r.y(), 2 * rBord, r.height()), true); 495 if (p >= 0) { 496 context->setStrokeStyle(NoStroke); 497 context->setFillColor(greyQuarterOpacity); 498 context->drawRect(IntRect(p + sw/2 - rBord, r.y(), 2 * rBord, r.height())); 499 } 500 } else { 501 if (m_oldpos >= 0) 502 v->updateContents(IntRect(r.x(), m_oldpos + sw/2 - rBord, r.width(), 2 * rBord), true); 503 if (p >= 0) { 504 context->setStrokeStyle(NoStroke); 505 context->setFillColor(greyQuarterOpacity); 506 context->drawRect(IntRect(r.x(), p + sw/2 - rBord, r.width(), 2 * rBord)); 507 } 508 } 509 m_oldpos = p; 510 511 v->unlockDrawingFocus(context); 512 v->enableFlushDrawing(); 513 } 514 515 return res; 516 } 517 518 void RenderFrameSet::setResizing(bool e) 519 { 520 m_resizing = e; 426 startResizing(m_cols, evt->pageX() - xPos()); 427 startResizing(m_rows, evt->pageY() - yPos()); 428 if (m_cols.m_splitBeingResized != noSplit || m_rows.m_splitBeingResized != noSplit) { 429 setIsResizing(true); 430 return true; 431 } 432 } 433 } else { 434 if (evt->type() == mousemoveEvent || evt->type() == mouseupEvent) { 435 continueResizing(m_cols, evt->pageX() - xPos()); 436 continueResizing(m_rows, evt->pageY() - yPos()); 437 if (evt->type() == mouseupEvent) { 438 setIsResizing(false); 439 return true; 440 } 441 } 442 } 443 444 return false; 445 } 446 447 void RenderFrameSet::setIsResizing(bool isResizing) 448 { 449 m_isResizing = isResizing; 521 450 for (RenderObject* p = parent(); p; p = p->parent()) 522 451 if (p->isFrameSet()) 523 static_cast<RenderFrameSet*>(p)->m_ clientResizing = m_resizing;452 static_cast<RenderFrameSet*>(p)->m_isChildResizing = isResizing; 524 453 if (Frame* frame = document()->frame()) 525 frame->eventHandler()->setResizingFrameSet(e ? element() : 0); 526 } 527 528 bool RenderFrameSet::canResize(int _x, int _y) 529 { 530 // if we haven't received a layout, then the gridLayout doesn't contain useful data yet 531 if (needsLayout() || !m_gridLayout[0] || !m_gridLayout[1]) 532 return false; 533 534 // check if we're over a horizontal or vertical boundary 535 int pos = m_gridLayout[1][0]; 536 for (int c = 1; c < element()->totalCols(); c++) 537 if (_x >= pos && _x <= pos+element()->border()) 538 return true; 539 540 pos = m_gridLayout[0][0]; 541 for (int r = 1; r < element()->totalRows(); r++) 542 if (_y >= pos && _y <= pos+element()->border()) 543 return true; 544 545 return false; 454 frame->eventHandler()->setResizingFrameSet(isResizing ? frameSet() : 0); 455 } 456 457 bool RenderFrameSet::isResizingRow() const 458 { 459 return m_isResizing && m_rows.m_splitBeingResized != noSplit; 460 } 461 462 bool RenderFrameSet::isResizingColumn() const 463 { 464 return m_isResizing && m_cols.m_splitBeingResized != noSplit; 465 } 466 467 bool RenderFrameSet::canResize(const IntPoint& p) const 468 { 469 return hitTestSplit(m_cols, p.x()) != noSplit || hitTestSplit(m_rows, p.y()) != noSplit; 470 } 471 472 bool RenderFrameSet::canResizeRow(const IntPoint& p) const 473 { 474 int r = hitTestSplit(m_rows, p.y() - yPos()); 475 return r != noSplit && m_rows.m_isSplitResizable[r]; 476 } 477 478 bool RenderFrameSet::canResizeColumn(const IntPoint& p) const 479 { 480 int c = hitTestSplit(m_cols, p.x() - xPos()); 481 return c != noSplit && m_cols.m_isSplitResizable[c]; 482 } 483 484 int RenderFrameSet::splitPosition(const GridAxis& axis, int split) const 485 { 486 if (needsLayout()) 487 return 0; 488 489 int borderThickness = frameSet()->border(); 490 491 int size = axis.m_sizes.size(); 492 if (!size) 493 return 0; 494 495 int position = 0; 496 for (int i = 0; i <= split && i < size; ++i) 497 position += axis.m_sizes[i] + borderThickness; 498 return position - borderThickness; 499 } 500 501 int RenderFrameSet::hitTestSplit(const GridAxis& axis, int position) const 502 { 503 if (needsLayout()) 504 return noSplit; 505 506 int borderThickness = frameSet()->border(); 507 if (borderThickness <= 0) 508 return noSplit; 509 510 size_t size = axis.m_sizes.size(); 511 if (!size) 512 return noSplit; 513 514 int splitPosition = axis.m_sizes[0]; 515 for (size_t i = 1; i < size; ++i) { 516 if (position >= splitPosition && position < splitPosition + borderThickness) 517 return i - 1; 518 splitPosition += borderThickness + axis.m_sizes[i]; 519 } 520 return noSplit; 546 521 } 547 522 … … 549 524 void RenderFrameSet::dump(TextStream* stream, DeprecatedString ind) const 550 525 { 551 *stream << " totalrows=" << element()->totalRows(); 552 *stream << " totalcols=" << element()->totalCols(); 553 554 unsigned i; 555 for (i = 0; i < (unsigned)element()->totalRows(); i++) 556 *stream << " hSplitvar(" << i << ")=" << m_hSplitVar[i]; 557 558 for (i = 0; i < (unsigned)element()->totalCols(); i++) 559 *stream << " vSplitvar(" << i << ")=" << m_vSplitVar[i]; 560 561 RenderContainer::dump(stream,ind); 526 *stream << " totalrows=" << frameSet()->totalRows(); 527 *stream << " totalcols=" << frameSet()->totalCols(); 528 529 for (int i = 0; i < frameSet()->totalRows(); i++) 530 *stream << " hSplitvar(" << i << ")=" << m_rows.m_isSplitResizable[i]; 531 532 for (int i = 0; i < frameSet()->totalCols(); i++) 533 *stream << " vSplitvar(" << i << ")=" << m_cols.m_isSplitResizable[i]; 534 535 RenderContainer::dump(stream,ind); 562 536 } 563 537 #endif -
trunk/WebCore/rendering/RenderFrameSet.h
r17494 r18333 26 26 #define RenderFrameSet_h 27 27 28 #include "HTMLFrameSetElement.h"29 28 #include "RenderContainer.h" 30 29 … … 35 34 36 35 class RenderFrameSet : public RenderContainer { 37 friend class HTMLFrameSetElement;38 36 public: 39 37 RenderFrameSet(HTMLFrameSetElement*); … … 44 42 45 43 virtual void layout(); 46 47 void positionFrames(); 48 49 bool resizing() const { return m_resizing; } 44 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); 50 45 51 46 bool userResize(MouseEvent*); 52 bool canResize(int x, int y);53 void setResizing(bool);54 47 55 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); 48 bool isResizingRow() const; 49 bool isResizingColumn() const; 56 50 57 HTMLFrameSetElement* element() const { return static_cast<HTMLFrameSetElement*>(RenderContainer::element()); } 51 bool canResizeRow(const IntPoint&) const; 52 bool canResizeColumn(const IntPoint&) const; 58 53 59 54 #ifndef NDEBUG 60 virtual void dump(TextStream* stream, DeprecatedString ind = "") const;55 virtual void dump(TextStream*, DeprecatedString ind = "") const; 61 56 #endif 62 57 63 58 private: 64 int m_oldpos; 65 int m_gridLen[2]; 66 int* m_gridDelta[2]; 67 int* m_gridLayout[2]; 59 static const int noSplit = -1; 68 60 69 bool* m_hSplitVar; // is this split variable? 70 bool* m_vSplitVar; 61 class GridAxis : Noncopyable { 62 public: 63 GridAxis(); 64 void resize(int); 65 Vector<int> m_sizes; 66 Vector<int> m_deltas; 67 Vector<bool> m_isSplitResizable; 68 int m_splitBeingResized; 69 int m_splitResizeOffset; 70 }; 71 71 72 int m_hSplit; // the split currently resized 73 int m_vSplit; 74 int m_hSplitPos; 75 int m_vSplitPos; 72 inline HTMLFrameSetElement* frameSet() const; 76 73 77 bool m_resizing; 78 bool m_clientResizing; 74 bool canResize(const IntPoint&) const; 75 void setIsResizing(bool); 76 77 void layOutAxis(GridAxis&, const Length*, int availableSpace); 78 void findNonResizableSplits(); 79 void positionFrames(); 80 81 int splitPosition(const GridAxis&, int split) const; 82 int hitTestSplit(const GridAxis&, int position) const; 83 84 void startResizing(GridAxis&, int position); 85 void continueResizing(GridAxis&, int position); 86 87 GridAxis m_rows; 88 GridAxis m_cols; 89 90 bool m_isResizing; 91 bool m_isChildResizing; 79 92 }; 80 93
Note: See TracChangeset
for help on using the changeset viewer.