When trying to make a good design you face situations in which you have to take a difficult decision that will easily affect the whole complexity of any further development.
“Design concerns”. That is how I call them. And some are really nasty!
From now on, I will share the troubles I stumble upon. Because not only will I annotate my current design concerns for future self-reference, but also let people participate with comments.
One of my current design issues I ran into was the relationship that a parent and its children keep in several ways, the most important of them being the selection of children.
Let’s imagine this situation:
We’ve got a designer surface with some items. This surface is the parent of every other items inside. Its children are Mario, a Button that says “Hola tío” (Hello dude), and the pretty obvious TextBox “This is my text”.
Knowing that it’s a designer with some elements into it, the user will expect some specific behavior. The most important are dragging and resizing.
Now the user sees Mario into a blue rectangle, remembers the times when they jumped all the way breaking blocks and decides “I will drag Mario!”. OK, the user expects Mario to be dragged around the surface.
STOP. Before moving anything we have to know what we want to move. How will we know that we have to move Mario?
ANSWER: Oh yes. In order to move him, we will have to select it first. So we will have some items that will be selected. Selected items! A common concept, uh?
OK, that sounds good.
Selected items, but what selected items? We need to select some of the children.
Clicking on the desired item should be enough. It’s the standard behavior. Isn’t it? So we decided that we will get the clicks on each item in order to know it has been selected to do something (dragging, for example).
- Create a boolean IsSelected property, for the class that will represent the item.
- Add an event handler to each child to capture the mouse click and change its state.
- On click, turn the IsSelected to true.
- Give the element the proper appearance when it’s selected.
Now, click every item and observe the goodness we achieved!
OK, you may have noticed that not only the items are selected individually, but also they is a concept of group in the capture. Just ignore it it’s part of my Glass library, currently being under development.
The fact is that we have a bunch of selected items that cannot be unselected. “Woahh, simple!” you will say. Just toggle IsSelected when clicking each time.
IsSelected = !ISelected;
Neat. Now you have more options. It’s alright. You win. But this is still far from being usable.
- First of all, when you have selected something and you want to drag it, each click will change the selection state.
- It’s really annoying to select items because most of times you will only want to select a single item: the one you just clicked. The others are discarded and only the newest should be the selected one.
I know, I know! there will be many times in which you will want to select multiple items. We definitely will have to handle those situations.
You may ask:
– Couldn’t I just intercept clicks on an item and then iterate through the rest of children in order to unselect them? In other words: each time I click one, I can unselect the others.
WRONG! If you click an item and this item and you make it responsible for changing the state of its neighbors, you’re giving it a really high responsibility. How could it be aware of each other item? That sounds like we’re breaking some very important rule.
If we have to interact with other neighbors but we’re just a little modest item that cannot say the others what to do (we don’t mind about them), who could help us to unselect the rest of the items if I, as a child, receive a click and I want to change my state?
To be continued…