Skip to content

10. Stack reorder

RhettTR edited this page Jan 16, 2024 · 1 revision

A stack of counters must be reordered. There are many ways of doing this. In the following one way is implemented.

Before going into the implementation it is important to say something about frames in Qt (QFrame).

Frames can be used as overlays stacked over each other. Think of a frame as a paint surface. In the part about stack inspection I used a top frame to paint stack sizes. This ensured that stack sizes were always visible, always on top of the counters making up a stack.

The hoover box for stack inspection was also painted on the top frame. It must always be visible when displayed. The hoover box is a child of the top frame.

There is a problem with frames stacked over each other. The top frame will grab mouse events and block any mouse events from reaching the lower frame. The simplest way to deal with this is to call setAttribute(Qt::WA_TransparentForMouseEvents, true) on the top frame. The problem then is that all mouse events pass the top frame. If you only paint on the top frame this is not a problem. But if you also want certain parts of the top frame to catch mouse events, you need allow it.

A very elegant way to do this in Qt is to use a mask. You can set a mask to be an arbitrary region (QRegion) of a frame. Only that part of the frame defined by the region gets mouse events.

void Overlay::paintEvent(QPaintEvent *e)
{    
    ...
	    
    clearMask();
    overlayMask = QRegion(0, 0, 1, 1);
    
    ...
    
    // render stack size numbers
    
    for (auto const& [point, stack] : stacks)	
    {	
    
	    int stackSize = (int)stack.size();
			    
	    if (stackSize > 1)
	    {	    
		    ...
		    
		    QRect rectangle = QRect(top->state.x + top->width - 8, 
					    top->state.y + top->margin + 2, 
					    16, 
					    16);
								    
		    overlayMask = overlayMask.united(rectangle);    
			    
		    ...
	    }
		    		    
    }
      
    
    if (openView->isVisible())
	    overlayMask = overlayMask.united(openView->geometry());
    
    if (hooverView->isVisible())
	    overlayMask = overlayMask.united(hooverView->geometry());
	        
	    
    setMask(overlayMask);

}

Both the stack size rectangles, the hoover view and the opened stack view for reordering are added to the mask. Strictly speaking the stack size rectangles do not need to be added.


Stack reordering will be implemented by displaying a box of counters making up the stack. The counters are displayed in stack order with the left most counter being the bottom counter. The reordering is done by dragging a counter to a new position.

A no-offset stack of four counters looks like this.

1.png

By double-clicking the stack you get a box with the stack contents ordered from left to right. Because the limit for a line is 3 counters the line has two rows.

2.png

You can now drag a counter to a new position in the stack by dropping it where it should go. Here the counter second from bottom is dragged to the top position.

3.png

The new stack looks like this.

4.png

By double clicking the stack again the updates are applied to the stack and the stack reorder box is closed. You can inspect the new stack by hoovering over it.

5.png

If you do not want to apply the changes you can hit the ESC button. This closes the stack reorder box and updates are not applied to the stack.


The complete code for stack reordering is found here.


CPLUS_INCLUDE_PATH=/opt/Qt6.5/include;export CPLUS_INCLUDE_PATH

LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/opt/Qt6.5/lib;export LD_LIBRARY_PATH

g++ -Wall -o main main.cpp luau.cpp counter.cpp window.cpp frame.cpp overlay.cpp -I/home/me/luau/VM/include -I/home/me/luau/Compiler/include -I/opt/Qt6.5/include/QtWidgets -Wl,--copy-dt-needed-entries -L/opt/Qt6.5/lib -lQt6Core -lQt6Widgets -L/home/me/luau/build/release -lluauvm -lluaucompiler -lluauast -lisocline

Clone this wiki locally