Removing or recoloring an elementTopFinding an item in an array

Finding an item in an array

The most interesting code in the program is the one to determine if the point clicked is inside any of the objects. See getIndexOf. Notice that if point is in several elements, selected will only refer to the last of these.

With this method at hand, it is easy to select a shape in order to drag it around (see selectShapeAt), but there is some work to be done to send it to the top and to move the item selected to be the last item in the array.

For example, suppose we initially create 4 items without doing any dragging. We then select an item and drag it so that it is now on top of the newest item. The first picture below shows the screen before the drag. The next picture shows the screen after the drag.

From these pictures, it is easy to see the layering order of the visible objects. The geomObjects array that we created in our code still has the elements in the array in the order that they were created. If we want the user's selection to refer to the topmost element, rather than the newest element, we should reorder the elements of our array to reflect the layering order in the display. Currently, when we select an item, we call sendToFront to get the item on the top of the visible layering. How should we update our array so that it reflects this change in the layering? We should make the selected item be the last entry in our array. To prevent having holes in the array, we should move all the other elements down. The picture below shows the original ordering in our array and how we need to shift the array elements to get the desired new ordering:

How would we accomplish this shift? We want to walk the array starting at our selected object and move each shape above it down one. Then we want to put the selected shape in the last element. In this way the order of elements in our array exactly mirrors the order in which they are layered on the screen. See method removeEltWithIndex.

Now when the last few lines of selectShapeAt are executed, this code behaves as desired. When you click on the screen. The top-most object clicked on is selected and popped to the top. A good thing to worry about is what would have happened if I had written the last for loop as:

            for (int objNum = numObjects; objNum > selectIndex; objNum--) {
               geomObject[objNum-1] = geomObject[objNum];
            }
Here we copy the last to the next to last slot, the next-to-last to the one before that, ..., until finally we copy the reference to the object at selectIndex+1 to the selectIndex slot. Can you see why this would not work properly? Simulate it by hand if you have difficulty seeing what goes wrong.

Perhaps you won't be surprised if I tell you that our DrawingCanvas class keeps track of a list of all the objects created involving the canvas. The reason we need to do this is that plain Java Canvases don't keep track of what is shown on them. Instead when a window is uncovered, it calls the repaint method, which first cleans up the window and then calls the paint method to redraw the window's contents. We do that by redrawing all of the items held in the list.


Removing or recoloring an elementTopFinding an item in an array