#include "global.h"
#include "mathconstants.h"
#include "painter.h"
+#include "penwidget.h"
#include "structs.h"
#include "utils.h"
-
#define BACKGROUND_MAX_SIZE 512
-
DrawingView::DrawingView(QWidget * parent/*= NULL*/): QWidget(parent),
// The value in the settings file will override this.
useAntialiasing(true), numHovered(0), shiftDown(false),
ctrlDown(false), altDown(false),
gridBackground(BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE),
- scale(1.0), offsetX(-10), offsetY(-10), document(true),
+ scale(1.0), offsetX(-10), offsetY(-10), supressSelected(false),
+ document(true),
gridPixels(0), collided(false), scrollDrag(false), hoverPointValid(false),
hoveringIntersection(false), dragged(NULL), draggingObject(false),
angleSnap(false), dirty(false)
setBackgroundRole(QPalette::Base);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ curMarker = QCursor(QPixmap(":/res/cursor-marker.png"), 1, 18);
+ curDropper = QCursor(QPixmap(":/res/cursor-dropper.png"), 1, 20);
+
Global::gridSpacing = 12.0; // In base units (inch is default)
Line * line = new Line(Vector(5, 5), Vector(50, 40), 2.0, 0xFF7F00, LSDash);
Need a way to scale line widths as well. :-/ Shouldn't be too difficult, just
need a thickness parameter similar to the "size" param for dimensions. (And now
we do! :-)
-
*/
- SetGridSize(12); // This is in pixels
}
-
-void DrawingView::SetGridSize(uint32_t size)
+void DrawingView::DrawBackground(Painter * painter)
{
- // Sanity check
- if (size == gridPixels)
- return;
+ Point ul = Painter::QtToCartesianCoords(Vector(0, 0));
+ Point br = Painter::QtToCartesianCoords(Vector(Global::screenSize.x, Global::screenSize.y));
- // Recreate the background bitmap
- gridPixels = size;
- QPainter pmp(&gridBackground);
- pmp.fillRect(0, 0, BACKGROUND_MAX_SIZE, BACKGROUND_MAX_SIZE, QColor(240, 240, 240));
- pmp.setPen(QPen(QColor(210, 210, 255), 2.0, Qt::SolidLine));
+ painter->SetBrush(0xF0F0F0);
+ painter->SetPen(0xF0F0F0, 1, 1);
+ painter->DrawRect(QRectF(QPointF(ul.x, ul.y), QPointF(br.x, br.y)));
- for(int i=0; i<(BACKGROUND_MAX_SIZE-1); i+=gridPixels)
- {
- pmp.drawLine(i, 0, i, BACKGROUND_MAX_SIZE - 1);
- pmp.drawLine(0, i, BACKGROUND_MAX_SIZE - 1, i);
- }
+ double spacing = Global::gridSpacing;
- pmp.end();
+ if (spacing < 1.0)
+ spacing = 1.0;
- // Set up new BG brush & zoom level (pixels per base unit)
- Global::zoom = gridPixels / Global::gridSpacing;
- UpdateGridBackground();
-}
+ double leftx = floor(ul.x / spacing) * spacing;
+ double bottomy = floor(br.y / spacing) * spacing;
+ double w = (br.x - ul.x) + Global::gridSpacing + 1.0;
+ double h = (ul.y - br.y) + Global::gridSpacing + 1.0;
-void DrawingView::UpdateGridBackground(void)
-{
- // Transform the origin to Qt coordinates
- Vector pixmapOrigin = Painter::CartesianToQtCoords(Vector());
- int x = (int)pixmapOrigin.x;
- int y = (int)pixmapOrigin.y;
- // Use mod arithmetic to grab the correct swatch of background
-/*
-Negative numbers still screw it up... Need to think about what we're
-trying to do here. The fact that it worked with 72 seems to have been pure luck.
-It seems the problem is negative numbers: We can't let that happen.
-When taking away the zero, it pops over 1 px at zero, then goes about 1/2 a
-grid at x<0.
-
-The bitmap looks like this:
-
-+---+---+---+---+---
-| | | | |
-| | | | |
-+---+---+---+---+---
-| | | | |
-| | | | |
-| | | | |
-
-@ x = 1, we want it to look like:
-
--+---+---+---+---+---
- | | | | |
- | | | | |
--+---+---+---+---+---
- | | | | |
- | | | | |
- | | | | |
-
-Which means we need to grab the sample from x = 3. @ x = -1:
-
----+---+---+---+---
- | | | |
- | | | |
----+---+---+---+---
- | | | |
- | | | |
- | | | |
-
-Which means we need to grab the sample from x = 1. Which means we have to take
-the mirror of the modulus of gridPixels.
-
-Doing a mod of a negative number is problematic: 1st, the compiler converts the
-negative number to an unsigned int, then it does the mod. Gets you wrong answers
-most of the time, unless you use a power of 2. :-P So what we do here is just
-take the modulus of the negation, which means we don't have to worry about
-mirroring it later.
-
-The positive case looks gruesome (and it is) but it boils down to this: We take
-the modulus of the X coordinate, then mirror it by subtraction from the
-maximum (in this case, gridPixels). This gives us a number in the range of 1 to
-gridPixels. But we need the case where the result equalling gridPixels to be
-zero; so we do another modulus operation on the result to achieve this.
-*/
- if (x < 0)
- x = -x % gridPixels;
- else
- x = (gridPixels - (x % gridPixels)) % gridPixels;
+ Vector start(leftx, bottomy), size(w, h);
- if (y < 0)
- y = -y % gridPixels;
- else
- y = (gridPixels - (y % gridPixels)) % gridPixels;
-
- // Here we grab a section of the bigger pixmap, so that the background
- // *looks* like it's scrolling...
- QPixmap pm = gridBackground.copy(x, y, gridPixels, gridPixels);
- QPalette pal = palette();
- pal.setBrush(backgroundRole(), QBrush(pm));
- setAutoFillBackground(true);
- setPalette(pal);
+ if (Global::gridSpacing <= 0.015625)
+ DrawSubGrid(painter, 0xFFD2D2, 0.015625, start, size);
+
+ if (Global::gridSpacing <= 0.03125)
+ DrawSubGrid(painter, 0xFFD2D2, 0.03125, start, size);
+
+ if (Global::gridSpacing <= 0.0625)
+ DrawSubGrid(painter, 0xB8ECFF, 0.0625, start, size);
+
+ if (Global::gridSpacing <= 0.125)
+ DrawSubGrid(painter, 0xB8ECFF, 0.125, start, size);
+
+ if (Global::gridSpacing <= 0.25)
+ DrawSubGrid(painter, 0xDBDBFF, 0.25, start, size);
+
+ if (Global::gridSpacing <= 0.5)
+ DrawSubGrid(painter, 0xDBDBFF, 0.5, start, size);
+
+ painter->SetPen(QPen(QColor(0xD2, 0xD2, 0xFF), 2.0, Qt::SolidLine));
+
+ for(double i=0; i<=w; i+=spacing)
+ painter->DrawVLine(leftx + i);
+
+ for(double i=0; i<=h; i+=spacing)
+ painter->DrawHLine(bottomy + i);
}
+void DrawingView::DrawSubGrid(Painter * painter, uint32_t color, double step, Vector start, Vector size)
+{
+ painter->SetPen(color, 1, 1);
+
+ for(double i=-step; i<=size.x; i+=step*2.0)
+ painter->DrawVLine(start.x + i);
+
+ for(double i=-step; i<=size.y; i+=step*2.0)
+ painter->DrawHLine(start.y + i);
+}
//
// Basically, we just make a single pass through the Container. If the layer #
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)
{
-// !!! FIX !!! This doesn't properly handle container contents...
//printf("DrawingView: Swapping layers %i and %i.\n", layer1, layer2);
- for(VPVectorIter i=document.objects.begin(); i!=document.objects.end(); i++)
+ HandleLayerSwap(layer1, layer2, document.objects);
+}
+
+/*
+We can roll this into the main one above, by having the LayerWidget's emit() call sending NULL for the VPVector, which we can test for and set to document.objects to grab the top layer. Or, keep it a top level call and a recursive call. Which is worse? :-P
+*/
+void DrawingView::HandleLayerSwap(int layer1, int layer2, VPVector & v)
+{
+ for(VPVectorIter i=v.begin(); i!=v.end(); i++)
{
Object * obj = (Object *)(*i);
obj->layer = layer2;
else if (obj->layer == layer2)
obj->layer = layer1;
+
+ if (obj->type == OTContainer)
+ HandleLayerSwap(layer1, layer2, ((Container *)obj)->objects);
}
}
-
void DrawingView::HandlePenWidth(float width)
{
for(VPVectorIter i=select.begin(); i!=select.end(); i++)
Object * obj = (Object *)(*i);
obj->thickness = width;
}
-}
+ supressSelected = true;
+ update();
+}
void DrawingView::HandlePenStyle(int style)
{
Object * obj = (Object *)(*i);
obj->style = style;
}
-}
+ supressSelected = true;
+ update();
+}
void DrawingView::HandlePenColor(uint32_t color)
{
Object * obj = (Object *)(*i);
obj->color = color;
}
-}
+ supressSelected = true;
+ update();
+}
-void DrawingView::HandlePenStamp(void)
+void DrawingView::HandlePenStamp(QAction * action)
{
- VPVector flat = Flatten(select);
+ PenWidget * pw = (PenWidget *)action->parentWidget();
+ pw->dropperAction->setChecked(false);
+ Global::penDropper = false;
+ Global::penStamp = action->isChecked();
- for(VPVectorIter i=flat.begin(); i!=flat.end(); i++)
- {
- Object * obj = (Object *)(*i);
-
- if (obj->type != OTText)
- obj->thickness = Global::penWidth;
+ if (Global::penStamp)
+ setCursor(curMarker);
+ else
+ setCursor(Qt::ArrowCursor);
- obj->style = Global::penStyle;
- obj->color = Global::penColor;
- }
+ if (Global::penStamp == false)
+ ClearSelected(document.objects);
update();
}
+void DrawingView::HandlePenDropper(QAction * action)
+{
+ PenWidget * pw = (PenWidget *)action->parentWidget();
+ pw->stampAction->setChecked(false);
+ Global::penStamp = false;
+ Global::penDropper = action->isChecked();
+
+ if (Global::penDropper)
+ setCursor(curDropper);
+ else
+ setCursor(Qt::ArrowCursor);
+
+ update();
+}
QPoint DrawingView::GetAdjustedMousePosition(QMouseEvent * event)
{
return QPoint(offsetX + event->x(), offsetY + (size().height() - event->y()));
}
-
QPoint DrawingView::GetAdjustedClientPosition(int x, int y)
{
// VOODOO ALERT (ON Y COMPONENT!!!!) (eh?)
return QPoint(-offsetX + x, (size().height() - (-offsetY + y)) * +1.0);
}
-
void DrawingView::focusOutEvent(QFocusEvent * /*event*/)
{
// printf("DrawingView::focusOutEvent()...\n");
setCursor(Qt::ArrowCursor);
}
+void DrawingView::focusInEvent(QFocusEvent * /*event*/)
+{
+ if (Global::penStamp)
+ setCursor(curMarker);
+ else if (Global::penDropper)
+ setCursor(curDropper);
+//FocusOut already set this...
+// else
+// setCursor(Qt::ArrowCursor);
+}
void DrawingView::paintEvent(QPaintEvent * /*event*/)
{
Global::viewportHeight = size().height();
+ DrawBackground(&painter);
+
// Draw coordinate axes
painter.SetPen(QPen(Qt::blue, 1.0, Qt::DotLine));
painter.DrawLine(0, -16384, 0, 16384);
painter.DrawInformativeText(informativeText);
}
-
//
// Renders objects in the passed in vector
//
painter->SetPen(obj->color, Global::zoom * scaledThickness, obj->style);
painter->SetBrush(obj->color);
- if (obj->selected || obj->hitObject)
+ // penStamp supresses object highlighting, so that changes can be seen.
+ if (supressSelected || Global::penStamp)
+ {
+ if (obj->hitObject)
+ {
+ painter->SetPen(Global::penColor, Global::zoom * Global::scale * Global::penWidth, Global::penStyle);
+ painter->SetBrush(Global::penColor);
+ }
+ }
+ else if (obj->selected || obj->hitObject)
painter->SetPen(0xFF0000, Global::zoom * scaledThickness, LSDash);
}
{
// Containers require recursive rendering...
Container * c = (Container *)obj;
-printf("About to render container: # objs=%i, layer=%i\n", (*c).objects.size(), layer);
+//printf("About to render container: # objs=%i, layer=%i\n", (*c).objects.size(), layer);
RenderObjects(painter, (*c).objects, layer, ignoreLayer);
//printf("Container extents: <%lf, %lf>, <%lf, %lf>\nsize: %i\n", r.l, r.t, r.r, r.b, c->objects.size());
break;
}
}
-}
+ supressSelected = false;
+}
//
// This toggles the selection being hovered (typically, only 1 object)
}
}
-
VPVector DrawingView::GetSelection(void)
{
VPVector v;
return v;
}
-
VPVector DrawingView::GetHovered(void)
{
VPVector v;
return v;
}
-
void DrawingView::resizeEvent(QResizeEvent * /*event*/)
{
Global::screenSize = Vector(size().width(), size().height());
- UpdateGridBackground();
}
-
void DrawingView::ToolHandler(int mode, Point p)
{
// Drop angle snap until it's needed
ParallelHandler(mode, p);
}
-
void DrawingView::ToolDraw(Painter * painter)
{
if (Global::tool == TTLine)
}
}
-
void DrawingView::LineHandler(int mode, Point p)
{
switch (mode)
}
}
-
void DrawingView::CircleHandler(int mode, Point p)
{
switch (mode)
}
}
-
void DrawingView::ArcHandler(int mode, Point p)
{
switch (mode)
}
}
-
void DrawingView::RotateHandler(int mode, Point p)
{
switch (mode)
}
}
-
void DrawingView::MirrorHandler(int mode, Point p)
{
switch (mode)
}
}
-
void DrawingView::DimensionHandler(int mode, Point p)
{
switch (mode)
}
}
-
void DrawingView::TriangulateHandler(int mode, Point/*p*/)
{
switch (mode)
}
}
-
void DrawingView::TrimHandler(int mode, Point p)
{
/*
}
}
-
void DrawingView::ParallelHandler(int mode, Point /*p*/)
{
switch (mode)
}
}
-
void DrawingView::mousePressEvent(QMouseEvent * event)
{
if (event->button() == Qt::LeftButton)
//printf("mousePressEvent::numHovered > 0 (hover2[0]=$%llx, type=%s)\n", dragged, objName[dragged->type]);
// Alert the pen widget
- emit ObjectSelected(dragged);
+// Maybe do this with an eyedropper tool on the pen bar? [YES]
+// emit ObjectSelected(dragged);
+ if (Global::penDropper)
+ {
+ Global::penColor = dragged->color;
+ Global::penWidth = dragged->thickness;
+ Global::penStyle = dragged->style;
+ emit ObjectSelected(dragged);
+ ClearSelected(document.objects);
+ return;
+ }
+
+ if (Global::penStamp)
+ {
+ dragged->color = Global::penColor;
+ dragged->thickness = Global::penWidth;
+ dragged->style = Global::penStyle;
+ return;
+ }
// See if anything is using just a straight click on a handle
if (HandleObjectClicked())
}
}
-
void DrawingView::mouseMoveEvent(QMouseEvent * event)
{
+ // It seems that wheelEvent() triggers this for some reason...
+ if (scrollWheelSeen)
+ {
+ scrollWheelSeen = false;
+ return;
+ }
+
Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
Global::selection.setBottomRight(QPointF(point.x, point.y));
// Only needs to be done here, as mouse down is always preceded by movement
delta.y = -delta.y;
Global::origin -= delta;
- UpdateGridBackground();
+// UpdateGridBackground();
update();
oldPoint = point;
return;
// Make sure previously selected objects stay selected (CTRL held)
for(VPVectorIter i=select.begin(); i!=select.end(); i++)
- ((Object *)(*i))->selected = true;
+ {
+ // Make sure *not* to select items on hidden layers
+ if (Global::layerHidden[((Object *)(*i))->layer] == false)
+ ((Object *)(*i))->selected = true;
+ }
update();
return;
update();
}
-
void DrawingView::mouseReleaseEvent(QMouseEvent * event)
{
if (event->button() == Qt::LeftButton)
else if (event->button() == Qt::MiddleButton)
{
scrollDrag = false;
- setCursor(Qt::ArrowCursor);
+
+ if (Global::penStamp)
+ setCursor(curMarker);
+ else if (Global::penDropper)
+ setCursor(curDropper);
+ else
+ setCursor(Qt::ArrowCursor);
+
+ // Need to convert this, since it's in Qt coordinates (for wheelEvent)
+ oldPoint = Painter::QtToCartesianCoords(oldPoint);
}
}
-
void DrawingView::wheelEvent(QWheelEvent * event)
{
- double zoomFactor = 1.25;
- QSize sizeWin = size();
- Vector center(sizeWin.width() / 2.0, sizeWin.height() / 2.0);
- center = Painter::QtToCartesianCoords(center);
+ double zoomFactor = 1.20;
+ scrollWheelSeen = true;
- // This is not centering for some reason. Need to figure out why. :-/
- if (event->delta() > 0)
+ if (event->angleDelta().y() < 0)
{
- if (Global::zoom > 20.0)
+ if (Global::zoom > 400.0)
return;
- Vector newOrigin = center - ((center - Global::origin) / zoomFactor);
- Global::origin = newOrigin;
Global::zoom *= zoomFactor;
}
else
{
- if (Global::zoom < 0.25)
+ if (Global::zoom < 0.125)
return;
- Vector newOrigin = center + ((-center + Global::origin) * zoomFactor);
- Global::origin = newOrigin;
Global::zoom /= zoomFactor;
}
-// Global::gridSpacing = gridPixels / Painter::zoom;
-// UpdateGridBackground();
- SetGridSize(Global::gridSpacing * Global::zoom);
- update();
-// zoomIndicator->setText(QString("Grid: %1\", BU: Inch").arg(Global::gridSpacing));
-}
+ Point np = Painter::QtToCartesianCoords(oldScrollPoint);
+ Global::origin += (oldPoint - np);
+ emit(NeedZoomUpdate());
+}
void DrawingView::keyPressEvent(QKeyEvent * event)
{
}
}
-
void DrawingView::keyReleaseEvent(QKeyEvent * event)
{
bool oldShift = shiftDown;
if (oldAlt != altDown)
{
scrollDrag = false;
- setCursor(Qt::ArrowCursor);
+
+ if (Global::penStamp)
+ setCursor(curMarker);
+ else if (Global::penDropper)
+ setCursor(curDropper);
+ else
+ setCursor(Qt::ArrowCursor);
}
}
-
//
// This looks strange, but it's really quite simple: We want a point that's
// more than half-way to the next grid point to snap there while conversely we
return point;
}
-
Point DrawingView::SnapPointToAngle(Point point)
{
// Snap to a single digit angle (using toolpoint #1 as the center)
return point;
}
-
Rect DrawingView::GetObjectExtents(Object * obj)
{
// Default to empty rect, if object checks below fail for some reason
return rect;
}
-
void DrawingView::CheckObjectBounds(void)
{
VPVectorIter i;
}
}
-
bool DrawingView::HitTestObjects(Point point)
{
VPVectorIter i;
return needUpdate;
}
-
bool DrawingView::HitTest(Object * obj, Point point)
{
bool needUpdate = false;
return needUpdate;
}
-
bool DrawingView::HandleObjectClicked(void)
{
if (dragged->type == OTDimension)
return false;
}
-
void DrawingView::HandleObjectMovement(Point point)
{
Point delta = point - oldPoint;
}
}
-
void DrawingView::AddDimensionTo(void * o)
{
Object * obj = (Object *)o;
break;
}
}
-