Added line object implementation.

This commit is contained in:
Jim Evins
2016-05-28 18:50:02 -04:00
parent cd24c96386
commit f447aed034
11 changed files with 501 additions and 45 deletions
+2
View File
@@ -37,6 +37,7 @@ set (glabels_sources
LabelModelObject.cpp
LabelModelBoxObject.cpp
LabelModelEllipseObject.cpp
LabelModelLineObject.cpp
LabelModelShapeObject.cpp
LabelRegion.cpp
MainWindow.cpp
@@ -80,6 +81,7 @@ set (glabels_qobject_headers
LabelModelObject.h
LabelModelBoxObject.h
LabelModelEllipseObject.h
LabelModelLineObject.h
LabelModelShapeObject.h
MainWindow.h
MergeView.h
+15 -1
View File
@@ -29,6 +29,7 @@
#include "LabelModelObject.h"
#include "LabelModelBoxObject.h"
#include "LabelModelEllipseObject.h"
#include "LabelModelLineObject.h"
#include "UndoRedoModel.h"
#include "Settings.h"
#include "Cursors.h"
@@ -339,6 +340,19 @@ LabelEditor::createEllipseMode()
}
///
/// Create line mode
///
void
LabelEditor::createLineMode()
{
setCursor( Cursors::Line() );
mCreateObjectType = Line;
mState = CreateIdle;
}
///
/// Resize Event Handler
///
@@ -475,7 +489,7 @@ LabelEditor::mousePressEvent( QMouseEvent* event )
mCreateObject = new LabelModelEllipseObject();
break;
case Line:
// mCreateObject = new LabelModelLineObject();
mCreateObject = new LabelModelLineObject();
break;
case Image:
// mCreateObject = new LabelModelImageObject();
+199
View File
@@ -0,0 +1,199 @@
/* LabelModelLineObject.cpp
*
* Copyright (C) 2013-2016 Jim Evins <evins@snaught.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "LabelModelLineObject.h"
#include <QBrush>
#include <QPen>
namespace
{
const double slopPixels = 2;
}
///
/// Constructor
///
LabelModelLineObject::LabelModelLineObject()
{
mOutline = 0;
mHandles << new HandleP1( this );
mHandles << new HandleP2( this );
mLineWidth = 1.0;
mLineColorNode = ColorNode( QColor( 0, 0, 0 ) );
}
///
/// Copy constructor
///
LabelModelLineObject::LabelModelLineObject( const LabelModelLineObject* object ) : LabelModelObject(object)
{
mLineWidth = object->mLineWidth;
mLineColorNode = object->mLineColorNode;
}
///
/// Destructor
///
LabelModelLineObject::~LabelModelLineObject()
{
foreach( Handle* handle, mHandles )
{
delete handle;
}
mHandles.clear();
}
///
/// Clone
///
LabelModelLineObject* LabelModelLineObject::clone() const
{
return new LabelModelLineObject( this );
}
///
/// Line Width Property Getter
///
glabels::Distance LabelModelLineObject::lineWidth( void ) const
{
return mLineWidth;
}
///
/// Line Width Property Setter
///
void LabelModelLineObject::setLineWidth( const glabels::Distance& value )
{
if ( mLineWidth != value )
{
mLineWidth = value;
emit changed();
}
}
///
/// Line Color Node Property Getter
///
ColorNode LabelModelLineObject::lineColorNode( void ) const
{
return mLineColorNode;
}
///
/// Line Color Node Property Setter
///
void LabelModelLineObject::setLineColorNode( const ColorNode& value )
{
if ( mLineColorNode != value )
{
mLineColorNode = value;
emit changed();
}
}
///
/// Can Line Color Capability Implementation
///
bool LabelModelLineObject::canLineColor()
{
return true;
}
///
/// Can Line Width Capability Implementation
///
bool LabelModelLineObject::canLineWidth()
{
return true;
}
///
/// Draw shadow of object
///
void LabelModelLineObject::drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const
{
QColor lineColor = mLineColorNode.color( record );
QColor shadowColor = mShadowColorNode.color( record );
shadowColor.setAlphaF( mShadowOpacity );
if ( lineColor.alpha() )
{
painter->setPen( QPen( shadowColor, mLineWidth.pt() ) );
painter->drawLine( 0, 0, mW.pt(), mH.pt() );
}
}
///
/// Draw object itself
///
void LabelModelLineObject::drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const
{
QColor lineColor = mLineColorNode.color( record );
painter->setPen( QPen( lineColor, mLineWidth.pt() ) );
painter->drawLine( 0, 0, mW.pt(), mH.pt() );
}
///
/// Path to test for hover condition
///
QPainterPath LabelModelLineObject::hoverPath( double scale ) const
{
QPainterPath path;
if ( mLineColorNode.color().alpha() )
{
//
// Build a thin rectangle representing line
//
double rPts = mLineWidth.pt()/2 + slopPixels / scale;
double lengthPts = sqrt( mW.pt()*mW.pt() + mH.pt()*mH.pt() );
double dx = mH.pt() / lengthPts; // horizontal pitch of perpendicular line
double dy = mW.pt() / lengthPts; // vertical pitch of perpendicular line
path.moveTo( rPts*dx, - rPts*dy );
path.lineTo( mW.pt() + rPts*dx, mH.pt() - rPts*dy );
path.lineTo( mW.pt() - rPts*dx, mH.pt() + rPts*dy );
path.lineTo( - rPts*dx, rPts*dy );
path.closeSubpath();
}
return path;
}
+94
View File
@@ -0,0 +1,94 @@
/* LabelModelLineObject.h
*
* Copyright (C) 2013-2016 Jim Evins <evins@snaught.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef LabelModelLineObject_h
#define LabelModelLineObject_h
#include "LabelModelObject.h"
///
/// Label Model Line Object
///
class LabelModelLineObject : public LabelModelObject
{
Q_OBJECT
///////////////////////////////////////////////////////////////
// Lifecycle Methods
///////////////////////////////////////////////////////////////
public:
LabelModelLineObject();
LabelModelLineObject( const LabelModelLineObject* object );
virtual ~LabelModelLineObject();
///////////////////////////////////////////////////////////////
// Object duplication
///////////////////////////////////////////////////////////////
virtual LabelModelLineObject* clone() const;
///////////////////////////////////////////////////////////////
// Property Implementations
///////////////////////////////////////////////////////////////
public:
//
// Line Property: lineWidth
//
virtual glabels::Distance lineWidth( void ) const;
virtual void setLineWidth( const glabels::Distance& value );
//
// Line Property: lineColorNode
//
virtual ColorNode lineColorNode( void ) const;
virtual void setLineColorNode( const ColorNode& value );
///////////////////////////////////////////////////////////////
// Capability Implementations
///////////////////////////////////////////////////////////////
public:
virtual bool canLineColor();
virtual bool canLineWidth();
///////////////////////////////////////////////////////////////
// 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;
///////////////////////////////////////////////////////////////
// Private Members
///////////////////////////////////////////////////////////////
protected:
glabels::Distance mLineWidth;
ColorNode mLineColorNode;
};
#endif // LabelModelLineObject_h
+8
View File
@@ -86,7 +86,15 @@ LabelModelObject::LabelModelObject( const LabelModelObject* object )
{
mHandles.append( handle->clone( this ) );
}
if ( object->mOutline )
{
mOutline = object->mOutline->clone( this );
}
else
{
mOutline = 0;
}
mMatrix = object->mMatrix;
}
+2 -1
View File
@@ -1235,7 +1235,8 @@ void MainWindow::objectsCreateBox()
///
void MainWindow::objectsCreateLine()
{
qDebug() << "ACTION: objects->Create->Line";
mUndoRedoModel->checkpoint( tr("Create Line") );
mLabelEditor->createLineMode();
}
+65 -2
View File
@@ -25,6 +25,7 @@
#include "LabelModelObject.h"
#include "LabelModelBoxObject.h"
#include "LabelModelEllipseObject.h"
#include "LabelModelLineObject.h"
#include "UndoRedoModel.h"
#include "Merge/Merge.h"
@@ -140,6 +141,26 @@ void ObjectEditor::loadRectSizePage()
}
void ObjectEditor::loadLineSizePage()
{
if ( mObject )
{
mBlocked = true;
sizeLineLengthSpin->setDecimals( mSpinDigits );
sizeLineLengthSpin->setSingleStep( mSpinStep );
sizeLineLengthSpin->setSuffix( " " + mUnits.toIdString() );
double w = mObject->w().inUnits(mUnits);
double h = mObject->h().inUnits(mUnits);
sizeLineLengthSpin->setValue( sqrt( w*w + h*h ) );
sizeLineAngleSpin->setValue( (180/M_PI)*atan2( h, w ) );
mBlocked = false;
}
}
void ObjectEditor::loadShadowPage()
{
if ( mObject )
@@ -213,12 +234,13 @@ void ObjectEditor::onSelectionChanged()
if ( dynamic_cast<LabelModelBoxObject*>(mObject) )
{
titleImageLabel->setPixmap( QPixmap(":icons/24x24/actions/glabels-box.png") );
titleLabel->setText( "Box object properties" );
titleLabel->setText( tr("Box object properties") );
notebook->addTab( lineFillPage, "line/fill" );
notebook->addTab( posSizePage, "position/size" );
notebook->addTab( shadowPage, "shadow" );
fillFrame->setVisible( true );
sizeRectFrame->setVisible( true );
sizeResetImageButton->setVisible( false );
sizeLineFrame->setVisible( false );
@@ -233,12 +255,13 @@ void ObjectEditor::onSelectionChanged()
else if ( dynamic_cast<LabelModelEllipseObject*>(mObject) )
{
titleImageLabel->setPixmap( QPixmap(":icons/24x24/actions/glabels-ellipse.png") );
titleLabel->setText( "Ellipse object properties" );
titleLabel->setText( tr("Ellipse object properties") );
notebook->addTab( lineFillPage, "line/fill" );
notebook->addTab( posSizePage, "position/size" );
notebook->addTab( shadowPage, "shadow" );
fillFrame->setVisible( true );
sizeRectFrame->setVisible( true );
sizeResetImageButton->setVisible( false );
sizeLineFrame->setVisible( false );
@@ -250,6 +273,27 @@ void ObjectEditor::onSelectionChanged()
setEnabled( true );
}
else if ( dynamic_cast<LabelModelLineObject*>(mObject) )
{
titleImageLabel->setPixmap( QPixmap(":icons/24x24/actions/glabels-line.png") );
titleLabel->setText( tr("Line object properties") );
notebook->addTab( lineFillPage, "line/fill" );
notebook->addTab( posSizePage, "position/size" );
notebook->addTab( shadowPage, "shadow" );
fillFrame->setVisible( false );
sizeRectFrame->setVisible( false );
sizeResetImageButton->setVisible( false );
sizeLineFrame->setVisible( true );
loadLineFillPage();
loadPositionPage();
loadLineSizePage();
loadShadowPage();
setEnabled( true );
}
else
{
Q_ASSERT_X( false, "ObjectEditor::onSelectionChanged", "Invalid object" );
@@ -288,6 +332,7 @@ void ObjectEditor::onObjectChanged()
{
loadLineFillPage();
loadRectSizePage();
loadLineSizePage();
loadShadowPage();
}
}
@@ -392,6 +437,24 @@ void ObjectEditor::onRectSizeControlsChanged()
}
void ObjectEditor::onLineSizeControlsChanged()
{
if ( !mBlocked )
{
mBlocked = true;
mUndoRedoModel->checkpoint( tr("Size") );
glabels::Distance spinLength = glabels::Distance(sizeLineLengthSpin->value(), mUnits);
double spinAngleRads = (M_PI/180)*sizeLineAngleSpin->value();
mObject->setSize( spinLength*cos(spinAngleRads), spinLength*sin(spinAngleRads) );
mBlocked = false;
}
}
void ObjectEditor::onShadowControlsChanged()
{
if ( !mBlocked )
+2
View File
@@ -59,6 +59,7 @@ private:
void loadLineFillPage();
void loadPositionPage();
void loadRectSizePage();
void loadLineSizePage();
void loadShadowPage();
@@ -77,6 +78,7 @@ private slots:
void onFillControlsChanged();
void onPositionControlsChanged();
void onRectSizeControlsChanged();
void onLineSizeControlsChanged();
void onShadowControlsChanged();
void onChanged();
+33 -2
View File
@@ -24,7 +24,7 @@
#include "LabelModelObject.h"
#include "LabelModelBoxObject.h"
#include "LabelModelEllipseObject.h"
//#include "LabelObjectLine.h"
#include "LabelModelLineObject.h"
//#include "LabelObjectImage.h"
//#include "LabelObjectBarcode.h"
#include "Merge/None.h"
@@ -133,6 +133,10 @@ XmlLabelCreator::addObjectsToNode( QDomElement &parent, const QList<LabelModelOb
{
createObjectEllipseNode( parent, ellipseObject );
}
else if ( LabelModelLineObject* lineObject = dynamic_cast<LabelModelLineObject*>(object) )
{
createObjectLineNode( parent, lineObject );
}
// TODO: other object types
else
{
@@ -233,7 +237,34 @@ XmlLabelCreator::createObjectEllipseNode( QDomElement &parent, const LabelModelE
void
XmlLabelCreator::createObjectLineNode( QDomElement &parent, const LabelModelLineObject* object )
{
// TODO
QDomDocument doc = parent.ownerDocument();
QDomElement node = doc.createElement( "Object-line" );
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, "dx", object->w() );
glabels::XmlUtil::setLengthAttr( node, "dy", 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() );
}
/* affine attrs */
createAffineAttrs( node, object );
/* shadow attrs */
createShadowAttrs( node, object );
}
+32 -3
View File
@@ -24,7 +24,7 @@
#include "LabelModelObject.h"
#include "LabelModelBoxObject.h"
#include "LabelModelEllipseObject.h"
//#include "LabelObjectLine.h"
#include "LabelModelLineObject.h"
//#include "LabelObjectImage.h"
//#include "LabelObjectBarcode.h"
#include "Merge/Factory.h"
@@ -266,11 +266,11 @@ XmlLabelParser::parseObjects( const QDomElement &node )
{
list.append( parseObjectEllipseNode( child.toElement() ) );
}
#if 0
else if ( tagName == "Object-line" )
{
list.append( parseObjectLineNode( child.toElement() ) );
}
#if 0
else if ( tagName == "Object-image" )
{
list.append( parseObjectImageNode( child.toElement() ) );
@@ -399,7 +399,36 @@ XmlLabelParser::parseObjectEllipseNode( const QDomElement &node )
LabelModelLineObject*
XmlLabelParser::parseObjectLineNode( const QDomElement &node )
{
return 0;
using namespace glabels;
LabelModelLineObject* object = new LabelModelLineObject();
/* 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, "dx", 0 ) );
object->setH( XmlUtil::getLengthAttr( node, "dy", 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 ) );
}
/* affine attrs */
parseAffineAttrs( node, object );
/* shadow attrs */
parseShadowAttrs( node, object );
return object;
}
+48 -35
View File
@@ -944,7 +944,7 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_5">
<widget class="QGroupBox" name="fillFrame">
<property name="title">
<string>Fill</string>
</property>
@@ -1253,6 +1253,18 @@
<property name="suffix">
<string notr="true"> °</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-180.000000000000000</double>
</property>
<property name="maximum">
<double>180.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
</layout>
@@ -1948,8 +1960,8 @@
<slot>onPositionControlsChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>90</x>
<y>112</y>
<x>153</x>
<y>132</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
@@ -2021,38 +2033,6 @@
</hint>
</hints>
</connection>
<connection>
<sender>sizeLineLengthSpin</sender>
<signal>valueChanged(double)</signal>
<receiver>ObjectEditor</receiver>
<slot>onChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>129</x>
<y>391</y>
</hint>
<hint type="destinationlabel">
<x>395</x>
<y>568</y>
</hint>
</hints>
</connection>
<connection>
<sender>sizeLineAngleSpin</sender>
<signal>valueChanged(double)</signal>
<receiver>ObjectEditor</receiver>
<slot>onChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>113</x>
<y>437</y>
</hint>
<hint type="destinationlabel">
<x>404</x>
<y>628</y>
</hint>
</hints>
</connection>
<connection>
<sender>shadowEnableCheck</sender>
<signal>toggled(bool)</signal>
@@ -2133,6 +2113,38 @@
</hint>
</hints>
</connection>
<connection>
<sender>sizeLineLengthSpin</sender>
<signal>valueChanged(double)</signal>
<receiver>ObjectEditor</receiver>
<slot>onLineSizeControlsChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>144</x>
<y>386</y>
</hint>
<hint type="destinationlabel">
<x>5</x>
<y>471</y>
</hint>
</hints>
</connection>
<connection>
<sender>sizeLineAngleSpin</sender>
<signal>valueChanged(double)</signal>
<receiver>ObjectEditor</receiver>
<slot>onLineSizeControlsChanged()</slot>
<hints>
<hint type="sourcelabel">
<x>120</x>
<y>437</y>
</hint>
<hint type="destinationlabel">
<x>1</x>
<y>510</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>onChanged()</slot>
@@ -2142,5 +2154,6 @@
<slot>onPositionControlsChanged()</slot>
<slot>onRectSizeControlsChanged()</slot>
<slot>onShadowControlsChanged()</slot>
<slot>onLineSizeControlsChanged()</slot>
</slots>
</ui>