-
-
Notifications
You must be signed in to change notification settings - Fork 997
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic shapes: oval and rectangle #358
Conversation
Thanks for PR. I had few things in mind. Let me review it and get back to you. |
First of all thanks for taking time and creating this PR. I really appreciated it. Initially I had an idea of allowing to add a custom view to the editor using API And I think we can start this idea with shapes. My ideas was to have a Pseudo code look like this. class ShapeView extends View {
// All the touch listener and setup goes here
void setShape(Shape shape)
void draw(){
shape.draw();
}
}
interface Shape{
void draw();
}
class Rectangle implements Shape
class Oval implements Shape Then we add a When client add the shape, we will add it into undo/redo stack as well as we do with I would like to not mixup the shape into
The challenge I see is on eraser implementation with each ShapeView. This was thought. Let me know your thoughts on this. |
Hi @burhanrashid52, I like your proposal, for several reasons. First, it's cleaner, and as you said, I felt that adding this to I can try to propose a first implementation of this in the next few days. I'll modify this PR. |
Yeah I like the idea of deletion since it's added as whole. |
I'll begin to work on this as soon as possible. I have some questions though. I'm not a Canvas specialist, so I'm not sure if I should have a Canvas (and a Path) for each Shape, or if I should have a unique one for all Shapes. The latter seems to prevent ease of creating individual items. What do you think of this? I didn't dive into your GraphicManager and what it does. Do you think I should use it or should I follow the DrawingView paradigm? Last question: would you consider starting to introduce Kotlin code in the lib or not? If OK, I'll write new code and classes in Kotlin. Thanks |
Yes having path for each shape will be more flexible. As I already mentioned that we can have common
I really want too. But I am avoiding this right now because.
I would happy if someone wants to take this. #360 |
Also the ui tests are failing. |
Hi @burhanrashid52, No problem for not using Kotlin for now, I was just asking. I know it is a bit of work, that can wait for now. I began to work on the subject, following what we said last week. With a bit more background on this, I now don't think we should have a Canvas for each Shape, but a Path for each Shape instead, all being drawn on a unique Canvas. In case of using multiple Canvas, we would have as many Views, then we should handle children of the parentView and their indexes, which is overkill (or maybe the GraphicManager may help here, I'm not sure). I think it would be simpler to just use a Path per Shape and generalize the current BrushDrawingView (the new ShapeView) to handle all the Shapes (brush could then be a Shape too). |
I did not get it. Can you elaborate or share a pseudo example. |
Here is what I did, which follows what we said earlier: First is ShapeView:
The Shape interface:
An example of Shape:
Then into
As I add the It it clearer? I have updated the PR with my current work, it will help you to understand. I also fixed the tests. |
import androidx.annotation.Nullable; | ||
|
||
|
||
public class ShapeView extends View { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to make package-private. We usually don't expose the internal representation of the view to client.
enum BrushDrawingShape { | ||
FREE_HAND, OVAL, RECTANGLE | ||
} | ||
void addShape(Shape shape); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use ShapeBuilder
pattern as we did for TextStyleBuilder
which provide more flexibility to add more properties to shape. And will also avoid to have this huge interface with too many methods.
photoeditor/src/main/java/ja/burhanrashid52/photoeditor/PhotoEditorImpl.java
Outdated
Show resolved
Hide resolved
photoeditor/src/main/java/ja/burhanrashid52/photoeditor/OvalShape.java
Outdated
Show resolved
Hide resolved
@@ -7,6 +7,8 @@ | |||
*/ | |||
public enum ToolType { | |||
BRUSH, | |||
OVAL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use just Shape
here since this is part of public it will break more often if we add/remove new Shapes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we can ventilate Shape choice directly from the Builder, so why not. Still, here we are on the app that makes use of the library, so it's less important to my opinion.
How would make the Shape selection then? A different enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now we just use ToolType.Shape
to indicate a Shape not the shape details. I am fine with another enum as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing is this enum is tightly coupled with the UI, as it is aligned with the tool selector. I will propose something simple to select the shape in the UI, but it is up to each developer to make its own implementation.
If add the view the way you have currently implemented then
|
@stephanepechard Any updates on this ? |
Here are my thoughts on this:
|
Sounds good 👍 |
+ adapt current demo UI + add a new Shape: Line
Hi @burhanrashid52, Here is a more consistant contribution. I've made the Shapes to be drawn on a unique dedicated ShapeView, as brush is. Each Shape is made of an internal Path and is configured/styled through a ShapeBuilder. To regroup common Shape code, I've added an abstract class that implements the Shape interface. Things could be even tighter around here, but it's not bad already. I've also added a new Shape, to draw lines. It's easy to add one with this implementation, you just need to specify how it is drawn in its own class. Style is handled the same way for all Shapes. I consider moving the Brush as a Shape in itself and therefore get rid of the BrushDrawingView as it is. What would think of it? It would be simpler to maintain, the Z-order of the views would be proper and the undo-redo feature would be easier to do. |
Sounds great. Will try to review by this week.
Yeah it make sense. We can treat Brush as independent Shape which will make undo-redo easier and consistent. |
photoeditor/src/main/java/ja/burhanrashid52/photoeditor/PhotoEditorImpl.java
Outdated
Show resolved
Hide resolved
I tested the code and found the undo/redo is not working with shapes. I think after reviewing the code I want to change my opinion on having a separate Now I see that why you preferred the Free shape in the beginning. I think you were right on keeping the If we can move the The only thing we need to make sure of is the We don't need to concern about #268 issue I mentioned in the previous comment. |
Yes, the merge of both views seem necessary, to keep all features and have a consistant code. |
Great 👍 Looking forward to it. I am excited to release this feature soon 😃 |
I'm almost done with the creation of a unique View (that I renamed DrawingView) with a functioning undo/redo. I remove the eraser as it was, as it does not reflect the new Shape architecture. I'm currently thinking about if whether we need a brushDrawindMode or not. |
I realized that with the new features, the removal of the eraser and some renaming, this new version will break the API. Can we consider updating the version number to 2.0.0 to reflect that? |
- BrushDrawingView is now called DrawingView - draw parameters (color, opacity, thickness) goes through a ShapeBuilder - undo-redo performs the same for all Shapes - fixed tests
Here is the commit. Quite a big one again, but we're close to the end I think. |
Ah!! We cannot remove the eraser. We need that for erasing with free hand on drawing and shapes. Currently I am not in state to manage big release and breaking changes. We can go the first approach on your first commit as we discussed. |
We need add Eraser back and rename |
I can't go back to my first commit, as Shapes are not removable at this point. |
Sounds good to me 👍 Also, can we rename |
No problem with renaming |
Here is a commit with the come back of the eraser and the addition of @deprecated annotations on some setters (not the getters after all, as they use the new model). |
I've tested the changes and it's working great but found few issues.
|
…order to undo/redo them as it was primarily
@burhanrashid52 Tell me if you see anything else. |
That's it. I will do just one round of testing and will merge it. Thank you so much for this effort and making it all works. 👍 |
I propose a basic implementation of adding oval and rectangle to an image. I added this as alternative shapes to the BrushDrawingView (default being the existing free hand). Paths are simply drawn depending on the selected tool.
Maybe you thought about this feature differently, please do comment if I need to revise my implementation.
I updated the demo app and added tests and documentation as well. I attach a view of the new tools in the toolbar and the rendering of such shapes. Icons are kinda trivial but understandable :-)
Resolves #72