Version 9 (modified by deni, 16 years ago) (diff) |
---|
Analysis
Overview
Currently frames can be resized using the Frame Size and Position halo button and hud. The user specifies new width and height, the frame content is resized accordingly and the frame location (top left corner) remains the same.
It would be convenient for the user to have another way of resizing the frame in addition to this one - by dragging the frame bounds with the mouse.
Task requirements
- There should be an invisible rectangular area around the border outline (the middle of the border) which could be used for resizing the frame.
- It should be divided into 8 subareas resposible for resizing in the 8 different directions - north, south, east, west and the intermediate north-east, north-west, south-west and south-east.
- When the user clicks on one of the subareas and starts dragging, the frame is resized in the appropriate way - if necessary its position is also changed. The opposite area is preserved. So if the user drags NW area the position and the size are changed so that SE area stays in place.
- The frame is resized while the user is dragging, not after he/she releases the mouse. Also if settings HUD is opened the data inside it should be updated before the mouse release. (This could be dropped for the next revision )
Task result
The result of this page should be source code.
Implementation idea
The 8 subareas could be 8 different scene elements (children of the frame scene element) with different responsible areas.
Related
How to demo
- Open Sophie application
- Create a new frame (populate content inside)
- Resize it.
Design
As described in the analysis, the resize area will be a thin rectangular area around the border outline.
It will be divided into 8 subareas in the following way:
- The border outline has 8 interesting points described in the Position enum - TOP_LEFT, MIDDLE_LEFT, etc.
- 8 rectangles with centers these points that are twice smaller than the border outline will be created.
- Each subarea will be constructed as the intersection of the resize area with one of these rectangles.
[picture...]
Each subarea changes the size and position of the frame in a different way, so that the opposite one stays in place.
Each subarea will have the position used for its construction (from the Position enum) and 2 coefficients - changeX and changeY.
changeX could be:
- 0 if the resize area does not change the width of the frame
- +1 if dragging this area down (increasing x) will make the frame bigger
- -1 if dragging this area down will make the frame smaller
The same applies for changeY
So if we drag some of the resize areas, the code that will resize the frame will look like:
Frame f; // the frame we're resizing ImmRect r; // the border outline RezizeAreSceneElement resizeArea; // the resize subarea ImmPoint startPos; // the initial position of the point we started to drag ImmPoint mousePos; // the current position of the mouse, i.e. we dragged the resize area from startPos to mousePos float width = r.getWidth() + resizeArea.changeX().get() * (startPos.getX() - mousePos.getX()); float height = r.getHeight() + resizeArea.changeY().get() * (startPos.getY() - mousePos.getY()); Position positionToKeep = resizeArea.position().get().getOpposite(); ImmPoint pointToKeep = r.getPoint(opposite); f.setSize(BoundMode.MID_BORDER, new ImmSize(width, height)); f.setLocation(BoundMode.MID_BORDER, positionToKeep, pointToKeep);
A new class ResizeAreaSceneElement extending DefaultSceneElement with the following fields will be created:
- public Prop<ImmRect> borderOutline();
- public Prop<Position> position();
- public Prop<Integer> changeX();
- public Prop<Integer> changeY();
In addition, it will override clip() to construct the clipping rectangle - with center borderOutline().get().getPoint(position().get()) and width and height twice as small as the border outline's width and height.
A new ElementHelper for resize area scene elements is needed - ResizeAreaElementHelper
In getResponsibleArea() it will construct a rectagular area around the border outline.
In FrameView 8 resize scene elements will be added. They will also be added as subelements of FrameView.sceneElement after the border element (the order is important because the resize area should be above the border).
A new controller used by FrameView to resize the frame will be created. It will consist of 3 operations:
- RESIZE_START
It has a filter with eventId = InputEventR3.MOUSE_CLICKED, source class - FrameView.class and tip class - ResizeAreaSceneElement.class
In the handle method it should save the current position of the border outline, so that it could be used for resizing later. It is necessary to do so because if we consider only the current state, the error accumulated will be too big.
- RESIZE
It has a filter with eventId = InputEventR3.MOUSE_DRAGGED, source class - FrameView.class and tip class - ResizeAreaSceneElement.class
In the handle method it will actually resize the frame
- RESIZE_END
It has a filter with eventId = InputEventR3.MOUSE_DRAGGED, source class - FrameView.class and tip class - ResizeAreaSceneElement.class
In the handle method it will log a change for the UndoManager, so that the resize action could be undone.
Implementation
(Describe and link the implementation results here (from the wiki or the repository).)
Testing
(Place the testing results here.)
Comments
- In frame HUD there should be lock button that locks the width to height. This may not be part of this revision, but is important.
- Please make sure the behavior is clear when the frame is rotated for example.