diff --git a/glabels/CMakeLists.txt b/glabels/CMakeLists.txt index 8799de3..a099c2c 100644 --- a/glabels/CMakeLists.txt +++ b/glabels/CMakeLists.txt @@ -36,6 +36,7 @@ set (glabels_sources LabelModel.cpp LabelModelObject.cpp LabelModelBoxObject.cpp + LabelModelEllipseObject.cpp LabelModelShapeObject.cpp LabelRegion.cpp MainWindow.cpp @@ -78,6 +79,7 @@ set (glabels_qobject_headers LabelModel.h LabelModelObject.h LabelModelBoxObject.h + LabelModelEllipseObject.h LabelModelShapeObject.h MainWindow.h MergeView.h diff --git a/glabels/LabelEditor.cpp b/glabels/LabelEditor.cpp index 338627c..3283f27 100644 --- a/glabels/LabelEditor.cpp +++ b/glabels/LabelEditor.cpp @@ -28,6 +28,7 @@ #include "LabelModel.h" #include "LabelModelObject.h" #include "LabelModelBoxObject.h" +#include "LabelModelEllipseObject.h" #include "UndoRedoModel.h" #include "Settings.h" #include "Cursors.h" @@ -325,6 +326,19 @@ LabelEditor::createBoxMode() } +/// +/// Create ellipse mode +/// +void +LabelEditor::createEllipseMode() +{ + setCursor( Cursors::Ellipse() ); + + mCreateObjectType = Ellipse; + mState = CreateIdle; +} + + /// /// Resize Event Handler /// @@ -458,7 +472,7 @@ LabelEditor::mousePressEvent( QMouseEvent* event ) mCreateObject = new LabelModelBoxObject(); break; case Ellipse: - // mCreateObject = new LabelModelEllipseObject(); + mCreateObject = new LabelModelEllipseObject(); break; case Line: // mCreateObject = new LabelModelLineObject(); diff --git a/glabels/LabelModelEllipseObject.cpp b/glabels/LabelModelEllipseObject.cpp new file mode 100644 index 0000000..e8be8ac --- /dev/null +++ b/glabels/LabelModelEllipseObject.cpp @@ -0,0 +1,157 @@ +/* LabelModelEllipseObject.cpp + * + * Copyright (C) 2013-2016 Jim Evins + * + * This file is part of gLabels-qt. + * + * gLabels-qt is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * gLabels-qt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gLabels-qt. If not, see . + */ + +#include "LabelModelEllipseObject.h" + +#include +#include + + +namespace +{ + const double slopPixels = 2; +} + + +/// +/// Constructor +/// +LabelModelEllipseObject::LabelModelEllipseObject() +{ +} + + +/// +/// Copy constructor +/// +LabelModelEllipseObject::LabelModelEllipseObject( const LabelModelEllipseObject* object ) : LabelModelShapeObject( object ) +{ +} + + +/// +/// Destructor +/// +LabelModelEllipseObject::~LabelModelEllipseObject() +{ +} + + +/// +/// Clone +/// +LabelModelEllipseObject* LabelModelEllipseObject::clone() const +{ + return new LabelModelEllipseObject( this ); +} + + +/// +/// Draw shadow of object +/// +void LabelModelEllipseObject::drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const +{ + QColor lineColor = mLineColorNode.color( record ); + QColor fillColor = mFillColorNode.color( record ); + QColor shadowColor = mShadowColorNode.color( record ); + + shadowColor.setAlphaF( mShadowOpacity ); + + if ( fillColor.alpha() ) + { + painter->setPen( Qt::NoPen ); + painter->setBrush( shadowColor ); + + if ( lineColor.alpha() ) + { + /* Has FILL and OUTLINE: adjust size to account for line width. */ + painter->drawEllipse( QRectF( -mLineWidth.pt()/2, + -mLineWidth.pt()/2, + (mW + mLineWidth).pt(), + (mH + mLineWidth).pt() ) ); + } + else + { + /* Has FILL, but no OUTLINE. */ + painter->drawEllipse( QRectF( 0, 0, mW.pt(), mH.pt() ) ); + } + } + else + { + if ( lineColor.alpha() ) + { + /* Has only OUTLINE. */ + painter->setPen( QPen( shadowColor, mLineWidth.pt() ) ); + painter->setBrush( Qt::NoBrush ); + + painter->drawEllipse( QRectF( 0, 0, mW.pt(), mH.pt() ) ); + } + } + +} + + +/// +/// Draw object itself +/// +void LabelModelEllipseObject::drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const +{ + QColor lineColor = mLineColorNode.color( record ); + QColor fillColor = mFillColorNode.color( record ); + + painter->setPen( QPen( lineColor, mLineWidth.pt() ) ); + painter->setBrush( fillColor ); + + painter->drawEllipse( QRectF( 0, 0, mW.pt(), mH.pt() ) ); +} + + +/// +/// Path to test for hover condition +/// +QPainterPath LabelModelEllipseObject::hoverPath( double scale ) const +{ + double s = 1 / scale; + + QPainterPath path; + + if ( mFillColorNode.color().alpha() && mLineColorNode.color().alpha() ) + { + path.addEllipse( -mLineWidth.pt()/2, -mLineWidth.pt()/2, (mW+mLineWidth).pt(), (mH+mLineWidth).pt() ); + } + else if ( mFillColorNode.color().alpha() && !(mLineColorNode.color().alpha()) ) + { + path.addEllipse( 0, 0, mW.pt(), mH.pt() ); + } + else if ( mLineColorNode.color().alpha() ) + { + path.addEllipse( (-mLineWidth.pt()/2) - s*slopPixels, + (-mLineWidth.pt()/2) - s*slopPixels, + (mW + mLineWidth).pt() + s*2*slopPixels, + (mH + mLineWidth).pt() + s*2*slopPixels ); + path.closeSubpath(); + path.addEllipse( mLineWidth.pt()/2 + s*slopPixels, + mLineWidth.pt()/2 + s*slopPixels, + (mW - mLineWidth).pt() - s*2*slopPixels, + (mH - mLineWidth).pt() - s*2*slopPixels ); + } + + return path; +} diff --git a/glabels/LabelModelEllipseObject.h b/glabels/LabelModelEllipseObject.h new file mode 100644 index 0000000..d321fe7 --- /dev/null +++ b/glabels/LabelModelEllipseObject.h @@ -0,0 +1,61 @@ +/* LabelModelEllipseObject.h + * + * Copyright (C) 2013-2016 Jim Evins + * + * This file is part of gLabels-qt. + * + * gLabels-qt is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * gLabels-qt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gLabels-qt. If not, see . + */ + +#ifndef LabelModelEllipseObject_h +#define LabelModelEllipseObject_h + + +#include "LabelModelShapeObject.h" + + +/// +/// Label Model Ellipse Object +/// +class LabelModelEllipseObject : public LabelModelShapeObject +{ + Q_OBJECT + + /////////////////////////////////////////////////////////////// + // Lifecycle Methods + /////////////////////////////////////////////////////////////// +public: + LabelModelEllipseObject(); + LabelModelEllipseObject( const LabelModelEllipseObject* object ); + virtual ~LabelModelEllipseObject(); + + + /////////////////////////////////////////////////////////////// + // Object duplication + /////////////////////////////////////////////////////////////// + virtual LabelModelEllipseObject* clone() const; + + + /////////////////////////////////////////////////////////////// + // Drawing operations + /////////////////////////////////////////////////////////////// +protected: + virtual void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const; + virtual void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const; + virtual QPainterPath hoverPath( double scale ) const; + +}; + + +#endif // LabelModelEllipseObject_h diff --git a/glabels/MainWindow.cpp b/glabels/MainWindow.cpp index 0c4ee40..d3df0b4 100644 --- a/glabels/MainWindow.cpp +++ b/glabels/MainWindow.cpp @@ -46,6 +46,7 @@ #include "PrintView.h" #include "LabelModel.h" #include "LabelModelBoxObject.h" +#include "LabelModelEllipseObject.h" #include "UndoRedoModel.h" #include "Icons.h" #include "File.h" @@ -1243,7 +1244,8 @@ void MainWindow::objectsCreateLine() /// void MainWindow::objectsCreateEllipse() { - qDebug() << "ACTION: objects->Create->Ellipse"; + mUndoRedoModel->checkpoint( tr("Create Ellipse") ); + mLabelEditor->createEllipseMode(); } diff --git a/glabels/ObjectEditor.cpp b/glabels/ObjectEditor.cpp index c921cf5..8849758 100644 --- a/glabels/ObjectEditor.cpp +++ b/glabels/ObjectEditor.cpp @@ -24,6 +24,7 @@ #include "LabelModel.h" #include "LabelModelObject.h" #include "LabelModelBoxObject.h" +#include "LabelModelEllipseObject.h" #include "UndoRedoModel.h" #include "Merge/Merge.h" @@ -229,6 +230,26 @@ void ObjectEditor::onSelectionChanged() setEnabled( true ); } + else if ( dynamic_cast(mObject) ) + { + titleImageLabel->setPixmap( QPixmap(":icons/24x24/actions/glabels-ellipse.png") ); + titleLabel->setText( "Ellipse object properties" ); + + notebook->addTab( lineFillPage, "line/fill" ); + notebook->addTab( posSizePage, "position/size" ); + notebook->addTab( shadowPage, "shadow" ); + + sizeRectFrame->setVisible( true ); + sizeResetImageButton->setVisible( false ); + sizeLineFrame->setVisible( false ); + + loadLineFillPage(); + loadPositionPage(); + loadRectSizePage(); + loadShadowPage(); + + setEnabled( true ); + } else { Q_ASSERT_X( false, "ObjectEditor::onSelectionChanged", "Invalid object" ); diff --git a/glabels/XmlLabelCreator.cpp b/glabels/XmlLabelCreator.cpp index 09bdcdc..e4902d8 100644 --- a/glabels/XmlLabelCreator.cpp +++ b/glabels/XmlLabelCreator.cpp @@ -23,7 +23,7 @@ #include "LabelModel.h" #include "LabelModelObject.h" #include "LabelModelBoxObject.h" -//#include "LabelObjectEllipse.h" +#include "LabelModelEllipseObject.h" //#include "LabelObjectLine.h" //#include "LabelObjectImage.h" //#include "LabelObjectBarcode.h" @@ -129,6 +129,10 @@ XmlLabelCreator::addObjectsToNode( QDomElement &parent, const QList(object) ) + { + createObjectEllipseNode( parent, ellipseObject ); + } // TODO: other object types else { @@ -185,7 +189,44 @@ XmlLabelCreator::createObjectBoxNode( QDomElement &parent, const LabelModelBoxOb void XmlLabelCreator::createObjectEllipseNode( QDomElement &parent, const LabelModelEllipseObject* object ) { - // TODO + QDomDocument doc = parent.ownerDocument(); + QDomElement node = doc.createElement( "Object-ellipse" ); + parent.appendChild( node ); + + /* position attrs */ + glabels::XmlUtil::setLengthAttr( node, "x", object->x0() ); + glabels::XmlUtil::setLengthAttr( node, "y", object->y0() ); + + /* size attrs */ + glabels::XmlUtil::setLengthAttr( node, "w", object->w() ); + glabels::XmlUtil::setLengthAttr( node, "h", object->h() ); + + /* line attrs */ + glabels::XmlUtil::setLengthAttr( node, "line_width", object->lineWidth() ); + if ( object->lineColorNode().fieldFlag() ) + { + glabels::XmlUtil::setStringAttr( node, "line_color_field", object->lineColorNode().key() ); + } + else + { + glabels::XmlUtil::setUIntAttr( node, "line_color", object->lineColorNode().rgba() ); + } + + /* fill attrs */ + if ( object->fillColorNode().fieldFlag() ) + { + glabels::XmlUtil::setStringAttr( node, "fill_color_field", object->fillColorNode().key() ); + } + else + { + glabels::XmlUtil::setUIntAttr( node, "fill_color", object->fillColorNode().rgba() ); + } + + /* affine attrs */ + createAffineAttrs( node, object ); + + /* shadow attrs */ + createShadowAttrs( node, object ); } diff --git a/glabels/XmlLabelParser.cpp b/glabels/XmlLabelParser.cpp index 9aefd81..d752238 100644 --- a/glabels/XmlLabelParser.cpp +++ b/glabels/XmlLabelParser.cpp @@ -23,7 +23,7 @@ #include "LabelModel.h" #include "LabelModelObject.h" #include "LabelModelBoxObject.h" -//#include "LabelObjectEllipse.h" +#include "LabelModelEllipseObject.h" //#include "LabelObjectLine.h" //#include "LabelObjectImage.h" //#include "LabelObjectBarcode.h" @@ -262,11 +262,11 @@ XmlLabelParser::parseObjects( const QDomElement &node ) { list.append( parseObjectBoxNode( child.toElement() ) ); } -#if 0 else if ( tagName == "Object-ellipse" ) { list.append( parseObjectEllipseNode( child.toElement() ) ); } +#if 0 else if ( tagName == "Object-line" ) { list.append( parseObjectLineNode( child.toElement() ) ); @@ -354,7 +354,45 @@ XmlLabelParser::parseObjectBoxNode( const QDomElement &node ) LabelModelEllipseObject* XmlLabelParser::parseObjectEllipseNode( const QDomElement &node ) { - return 0; + using namespace glabels; + + LabelModelEllipseObject* object = new LabelModelEllipseObject(); + + + /* position attrs */ + object->setX0( XmlUtil::getLengthAttr( node, "x", 0.0 ) ); + object->setY0( XmlUtil::getLengthAttr( node, "y", 0.0 ) ); + + /* size attrs */ + object->setW( XmlUtil::getLengthAttr( node, "w", 0 ) ); + object->setH( XmlUtil::getLengthAttr( node, "h", 0 ) ); + + /* line attrs */ + object->setLineWidth( XmlUtil::getLengthAttr( node, "line_width", 1.0 ) ); + { + QString key = XmlUtil::getStringAttr( node, "line_color_field", "" ); + bool field_flag = !key.isEmpty(); + uint32_t color = XmlUtil::getUIntAttr( node, "line_color", 0 ); + + object->setLineColorNode( ColorNode( field_flag, color, key ) ); + } + + /* fill attrs */ + { + QString key = XmlUtil::getStringAttr( node, "line_color_field", "" ); + bool field_flag = !key.isEmpty(); + uint32_t color = XmlUtil::getUIntAttr( node, "fill_color", 0 ); + + object->setFillColorNode( ColorNode( field_flag, color, key ) ); + } + + /* affine attrs */ + parseAffineAttrs( node, object ); + + /* shadow attrs */ + parseShadowAttrs( node, object ); + + return object; }