// STILL TO BE DONE:
//
// - Lots of stuff
+// - Layer locking (hiding works)
//
// Uncomment this for debugging...
line->thickness = 2.0;
line->style = LSDash;
line->color = 0xFF7F00;
+ line->layer = 0;
document.objects.push_back(line);
document.objects.push_back(new Line(Vector(50, 40), Vector(10, 83)));
document.objects.push_back(new Line(Vector(10, 83), Vector(17, 2)));
}
-void DrawingView::SetCurrentLayer(int layer)
+void DrawingView::SetCurrentLayer(int /*layer*/)
{
- Global::currentLayer = layer;
+//Not needed anymore...
+// Global::currentLayer = layer;
//printf("DrawingView::CurrentLayer = %i\n", layer);
}
+//
+// Basically, we just make a single pass through the Container. If the layer #
+// is less than the layer # being deleted, then do nothing. If the layer # is
+// equal to the layer # being deleted, then delete the object. If the layer #
+// is greater than the layer # being deleted, then set the layer # to its layer
+// # - 1.
+//
+void DrawingView::DeleteCurrentLayer(int layer)
+{
+//printf("DrawingView::DeleteCurrentLayer(): currentLayer = %i\n", layer);
+ std::vector<void *>::iterator i = document.objects.begin();
+
+ while (i != document.objects.end())
+ {
+ Object * obj = (Object *)(*i);
+
+ if (obj->layer < layer)
+ i++;
+ else if (obj->layer == layer)
+ {
+ document.objects.erase(i);
+ delete obj;
+ }
+ else
+ {
+ obj->layer--;
+ i++;
+ }
+ }
+
+ // We've just done a destructive action, so update the screen!
+ update();
+}
+
+
+void DrawingView::HandleLayerToggle(void)
+{
+ // A layer's visibility was toggled, so update the screen...
+ update();
+}
+
+
+//
+// A layer was moved up or down in the layer list, so we have to swap the
+// document's object's layer numbers in the layers that were swapped.
+//
+void DrawingView::HandleLayerSwap(int layer1, int layer2)
+{
+//printf("DrawingView: Swapping layers %i and %i.\n", layer1, layer2);
+ std::vector<void *>::iterator i;
+
+ for(i=document.objects.begin(); i!=document.objects.end(); i++)
+ {
+ Object * obj = (Object *)(*i);
+
+ if (obj->layer == layer1)
+ obj->layer = layer2;
+ else if (obj->layer == layer2)
+ obj->layer = layer1;
+ }
+}
+
+
QPoint DrawingView::GetAdjustedMousePosition(QMouseEvent * event)
{
// This is undoing the transform, e.g. going from client coords to local coords.
painter.DrawLine(-16384, 0, 16384, 0);
// Do object rendering...
- RenderObjects(&painter, document.objects);
+ for(int i=0; i<Global::numLayers; i++)
+ {
+ if (Global::layerHidden[i] == false)
+ RenderObjects(&painter, document.objects, i);
+ }
// Do tool rendering, if any...
if (Global::tool)
//
// Renders objects in the passed in vector
//
-void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v)
+void DrawingView::RenderObjects(Painter * painter, std::vector<void *> & v, int layer)
{
std::vector<void *>::iterator i;
Object * obj = (Object *)(*i);
float scaledThickness = Global::scale * obj->thickness;
+ // If the object isn't on the current layer being drawn, skip it
+ if (obj->layer != layer)
+ continue;
+
if ((Global::tool == TTRotate) && ctrlDown && obj->selected)
{
painter->SetPen(0x00FF00, 2.0, LSSolid);
else
{
Line * l = new Line(toolPoint[0], toolPoint[1]);
+ l->layer = Global::activeLayer;
document.objects.push_back(l);
toolPoint[0] = toolPoint[1];
}
{
double length = Vector::Magnitude(toolPoint[0], toolPoint[1]);
Circle * c = new Circle(toolPoint[0], length);
+ c->layer = Global::activeLayer;
document.objects.push_back(c);
toolPoint[0] = toolPoint[1];
Global::toolState = TSNone;
span += PI_TIMES_2;
Arc * arc = new Arc(toolPoint[0], toolPoint[1].x, toolPoint[2].x, span);
+ arc->layer = Global::activeLayer;
document.objects.push_back(arc);
Global::toolState = TSNone;
}
#include "layeritemwidget.h"
-LayerItemWidget::LayerItemWidget(QString s, bool invisible/*=false*/, bool locked/*=false*/):
+LayerItemWidget::LayerItemWidget(QString s, bool i/*=false*/, bool l/*=false*/, QListWidgetItem * p/*=null*/):
QWidget(),
name(new QLabel(s)),
- visibility(new QPushButton),
- editibility(new QPushButton)
+ invisible(new QPushButton),
+ locked(new QPushButton),
+ parent(p)
{
QIcon visibleIcon(":/res/eye-open.png");
visibleIcon.addFile(":/res/eye-closed.png", QSize(16, 16), QIcon::Normal, QIcon::On);
QSize buttonSize(20, 20);
QHBoxLayout * mainLayout = new QHBoxLayout;
- mainLayout->setContentsMargins(0, 0, 0, 0); // This is required, otherwise the layout engine puts too much space around this widget. :-/
-
- visibility->setFlat(true);
- visibility->setIcon(visibleIcon);
- visibility->setCheckable(true);
- visibility->setMaximumSize(buttonSize);
- visibility->setChecked(invisible);
-
- editibility->setFlat(true);
- editibility->setIcon(lockedIcon);
- editibility->setCheckable(true);
- editibility->setMaximumSize(buttonSize);
- editibility->setChecked(locked);
-
- mainLayout->addWidget(visibility);
- mainLayout->addWidget(editibility);
+ // This is required, otherwise the layout engine puts too much space around
+ // this widget. :-/
+ mainLayout->setContentsMargins(0, 0, 0, 0);
+
+ invisible->setFlat(true);
+ invisible->setIcon(visibleIcon);
+ invisible->setCheckable(true);
+ invisible->setMaximumSize(buttonSize);
+ invisible->setChecked(i);
+
+ locked->setFlat(true);
+ locked->setIcon(lockedIcon);
+ locked->setCheckable(true);
+ locked->setMaximumSize(buttonSize);
+ locked->setChecked(l);
+
+ mainLayout->addWidget(invisible);
+ mainLayout->addWidget(locked);
mainLayout->addWidget(name);
setLayout(mainLayout);
+ connect(invisible, SIGNAL(clicked(bool)), this, SLOT(HandleHideToggle(bool)));
+ connect(locked, SIGNAL(clicked(bool)), this, SLOT(HandleLockToggle(bool)));
}
{
}
+
+void LayerItemWidget::HandleHideToggle(bool state)
+{
+// printf("Eye is: %s\n", !state ? "OPEN" : "closed");
+ emit(HideToggled(parent, state));
+}
+
+
+void LayerItemWidget::HandleLockToggle(bool state)
+{
+// printf("Lock is: %s\n", !state ? "OPEN" : "closed");
+ emit(LockToggled(parent, state));
+}
+
editLayer(new QToolButton), layerUp(new QToolButton),
layerDown(new QToolButton), list(new QListWidget)
{
- LayerItemWidget * liw = new LayerItemWidget("Background");
QListWidgetItem * qlwi = new QListWidgetItem(list);
+ LayerItemWidget * liw = new LayerItemWidget("Background", false, false, qlwi);
list->setItemWidget(qlwi, liw);
-// QToolButton * pb1 = new QToolButton;
-// QToolButton * pb2 = new QToolButton;
-// QToolButton * pb3 = new QToolButton;
-// QToolButton * pb4 = new QToolButton;
-// QToolButton * pb5 = new QToolButton;
-
addLayer->setIcon(QIcon(":/res/layer-add.png"));
removeLayer->setIcon(QIcon(":/res/layer-delete.png"));
editLayer->setIcon(QIcon(":/res/layer-edit.png"));
setLayout(mainLayout);
connect(list, SIGNAL(currentRowChanged(int)), this, SLOT(HandleLayerSelected(int)));
+ connect(list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(HandleDblClick(QListWidgetItem *)));
connect(addLayer, SIGNAL(clicked()), this, SLOT(AddLayer()));
connect(removeLayer, SIGNAL(clicked()), this, SLOT(DeleteLayer()));
connect(editLayer, SIGNAL(clicked()), this, SLOT(EditLayer()));
connect(layerUp, SIGNAL(clicked()), this, SLOT(MoveLayerUp()));
connect(layerDown, SIGNAL(clicked()), this, SLOT(MoveLayerDown()));
+ connect(liw, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
+ connect(liw, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
+
list->setCurrentRow(0);
+
+ // We set global variables here, since we are 'in charge' of them (mostly)
+ Global::activeLayer = 0;
+ Global::numLayers = 1;
+ Global::layerHidden.clear();
+ Global::layerLocked.clear();
+ Global::layerHidden.push_back(false);
+ Global::layerLocked.push_back(false);
}
//printf("LayerWidget::HandleLayerSelected(): currentRow = %i\n", currentRow);
// emit(LayerSelected(currentRow));
- QListWidgetItem * qlwi = list->item(currentRow);
- LayerItemWidget * li = (LayerItemWidget *)list->itemWidget(qlwi);
- Global::activeLayer = currentRow;
- Global::layerIsLocked = li->editibility->isChecked();
-
+ // This is numbered opposite of how it's presented. In other words, the
+ // bottom of the list is 0, and items above it count upwards. So like this:
+ //
+ // (2) Layer #2
+ // (1) Layer #1
+ // (0) Background
+ //
+ // which is the opposite of the internal numbering.
+ Global::activeLayer = (Global::numLayers - currentRow) - 1;
+//printf("LayerWidget::HandleLayerSelected(): currentRow = %i, numLayers = %i, active = %i\n", currentRow, Global::numLayers, Global::activeLayer);
// Set button states to sane values
SetButtonStates();
}
+//
+// What happens here is that for every QListWidgetItem we make, we connect it
+// to these handlers. But we only have to worry about that when adding and
+// moving a layer. However, when toggling states, we need to toggle the global
+// state variables too.
+//
+void LayerWidget::HandleHideToggle(QListWidgetItem * qlwi, bool state)
+{
+ int currentRow = list->row(qlwi);
+ int layer = (Global::numLayers - currentRow) - 1;
+ std::vector<bool>::iterator i = Global::layerHidden.begin() + layer;
+ (*i) = state;
+//printf("Item #%i, new hide state is %s\n", currentRow, (state ? "ON" : "off"));
+//printf("LayerWidget: New hide state of layer %i is %s.\n", layer, (state ? "ON" : "off"));
+ // We do this last, because otherwise the Document would get the wrong state
+ emit(LayerToggled());
+}
+
+
+void LayerWidget::HandleLockToggle(QListWidgetItem * qlwi, bool state)
+{
+ int currentRow = list->row(qlwi);
+ int layer = (Global::numLayers - currentRow) - 1;
+ std::vector<bool>::iterator i = Global::layerLocked.begin() + layer;
+ (*i) = state;
+// printf("Item #%i, new lock state is %s\n", list->row(qlwi), (state ? "ON" : "off"));
+}
+
+
+void LayerWidget::HandleDblClick(QListWidgetItem * /*qlwi*/)
+{
+ EditLayer();
+}
+
+
void LayerWidget::AddLayer(void)
{
+ // We always stick the newest layer at the top of the list...
int count = list->count();
QString text = QString("Layer #%1").arg(count);
- LayerItemWidget * liw = new LayerItemWidget(text);
QListWidgetItem * qlwi = new QListWidgetItem();
+ LayerItemWidget * liw = new LayerItemWidget(text, false, false, qlwi);
list->insertItem(0, qlwi);
list->setItemWidget(qlwi, liw);
+ // Set up SIGNAL/SLOTs for this LayerItemWidget
+ connect(liw, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
+ connect(liw, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
+
SetButtonStates();
+
+ // Fix up the global state
+ Global::layerHidden.insert(Global::layerHidden.begin(), false);
+ Global::layerLocked.insert(Global::layerLocked.begin(), false);
+ Global::numLayers++;
}
if (numItems == 1)
return;
+ // N.B.: This *must* go before the item removal because that causes
+ // HandleLayerSelected() to be fired off which causes the numbers to
+ // be off. You have been warned!
+ // Tell the DrawingView to delete this layer in its Container:
+ emit(LayerDeleted(Global::activeLayer));
+
+ int currentRow = list->currentRow();
QListWidgetItem * qlwi = list->currentItem();
list->removeItemWidget(qlwi);
delete qlwi;
SetButtonStates();
- // N.B.: Also, we need to delete the layer in the Drawing as well!
+ // Fix up the global state
+ int layer = (Global::numLayers - currentRow) - 1;
+ Global::layerHidden.erase(Global::layerHidden.begin() + layer);
+ Global::layerLocked.erase(Global::layerLocked.begin() + layer);
+ Global::numLayers--;
+
+ // If we're deleting from the top of the list, we have to decrement the
+ // active layer # by 1 (since we count upward from the bottom of the list).
+ if (currentRow == 0)
+ Global::activeLayer--;
}
QListWidgetItem * qlwi = list->currentItem();
LayerItemWidget * li = (LayerItemWidget *)list->itemWidget(qlwi);
QString s = li->name->text();
- bool visible = li->visibility->isChecked();
- bool editible = li->editibility->isChecked();
+ bool visible = li->invisible->isChecked();
+ bool editible = li->locked->isChecked();
// We have to make a new LayerItemWidget because it destroys the old one!
list->takeItem(currentRow);
list->insertItem(currentRow - 1, qlwi);
- li = new LayerItemWidget(s, visible, editible);
+ li = new LayerItemWidget(s, visible, editible, qlwi);
list->setItemWidget(qlwi, li);
list->setCurrentItem(qlwi);
+
+ // Set up SIGNAL/SLOTs for this LayerItemWidget
+ connect(li, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
+ connect(li, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
+
+ // Fix up the global state...
+ // N.B.: Because we handle the button states correctly, we should never
+ // have a situation where the reference in the vector is bad.
+ int layer = (Global::numLayers - currentRow) - 1;
+ bool old = Global::layerHidden[layer];
+ Global::layerHidden[layer] = Global::layerHidden[layer + 1];
+ Global::layerHidden[layer + 1] = old;
+ old = Global::layerLocked[layer];
+ Global::layerLocked[layer] = Global::layerLocked[layer + 1];
+ Global::layerLocked[layer + 1] = old;
+ // We also have to tell the document to shuffle its layers too
+ emit(LayersSwapped(layer, layer + 1));
}
QListWidgetItem * qlwi = list->currentItem();
LayerItemWidget * li = (LayerItemWidget *)list->itemWidget(qlwi);
QString s = li->name->text();
- bool visible = li->visibility->isChecked();
- bool editible = li->editibility->isChecked();
+ bool visible = li->invisible->isChecked();
+ bool editible = li->locked->isChecked();
// We have to make a new LayerItemWidget because it destroys the old one!
list->takeItem(currentRow);
list->insertItem(currentRow + 1, qlwi);
- li = new LayerItemWidget(s, visible, editible);
+ li = new LayerItemWidget(s, visible, editible, qlwi);
list->setItemWidget(qlwi, li);
list->setCurrentItem(qlwi);
+
+ // Set up SIGNAL/SLOTs for this LayerItemWidget
+ connect(li, SIGNAL(HideToggled(QListWidgetItem *, bool)), this, SLOT(HandleHideToggle(QListWidgetItem *, bool)));
+ connect(li, SIGNAL(LockToggled(QListWidgetItem *, bool)), this, SLOT(HandleLockToggle(QListWidgetItem *, bool)));
+
+ // Fix up the global state...
+ // N.B.: Because we handle the button states correctly, we should never
+ // have a situation where the reference in the vector is bad.
+ int layer = (Global::numLayers - currentRow) - 1;
+ bool old = Global::layerHidden[layer];
+ Global::layerHidden[layer] = Global::layerHidden[layer - 1];
+ Global::layerHidden[layer - 1] = old;
+ old = Global::layerLocked[layer];
+ Global::layerLocked[layer] = Global::layerLocked[layer - 1];
+ Global::layerLocked[layer - 1] = old;
+ // We also have to tell the document to shuffle its layers too
+ emit(LayersSwapped(layer, layer - 1));
}