Commit 9dbd9bd1 authored by Florent D'Halluin's avatar Florent D'Halluin
Browse files

[yavgui] Improve transition creation.

Handle transition creation in GScene (instead of GState).
Add transition preview.

* yavgui/src/Makefile.am: Add new files.
* yavgui/src/g_scene.cc,
* yavgui/src/g_scene.hh: Add implementation.
* yavgui/src/g_state.cc,
* yavgui/src/g_state.hh,
* yavgui/src/g_state.hxx: Remove obsolete code, fix (de)selection.
* yavgui/src/g_transition.cc,
* yavgui/src/g_transition.hh,
* yavgui/src/g_vcsn_handler_internal.hxx: Fix item (de)selection.
* yavgui/src/g_transition_draft.cc,
* yavgui/src/g_transition_draft.hh: New.  Floating preview.
parent 9268b78d
2009-08-10 d-halluin <d-halluin@lrde.epita.fr>
[yavgui] Improve transition creation.
Handle transition creation in GScene (instead of GState).
Add transition preview.
* yavgui/src/Makefile.am: Add new files.
* yavgui/src/g_scene.cc,
* yavgui/src/g_scene.hh: Add implementation.
* yavgui/src/g_state.cc,
* yavgui/src/g_state.hh,
* yavgui/src/g_state.hxx: Remove obsolete code, fix (de)selection.
* yavgui/src/g_transition.cc,
* yavgui/src/g_transition.hh,
* yavgui/src/g_vcsn_handler_internal.hxx: Fix item (de)selection.
* yavgui/src/g_transition_draft.cc,
* yavgui/src/g_transition_draft.hh: New. Floating preview.
2009-08-09 d-halluin <d-halluin@lrde.epita.fr>
 
[yavgui] Allow drawing of looping transitions.
......
......@@ -44,18 +44,20 @@ COMMON_SOURCES = main.cc \
g_scene.cc \
g_scene.moc.cc \
g_state.cc \
g_state.moc.cc \
g_vcsn_handler.cc \
g_vcsn_handler.moc.cc \
g_transition.cc \
g_painter.cc \
g_state.moc.cc \
g_transition.moc.cc \
gui.moc.cc \
vcsn_command.moc.cc \
g_transition_draft.cc \
g_transition_draft.moc.cc \
g_painter.cc \
command_list.cc \
vcsn_command.cc \
vcsn_command.moc.cc \
vcsn_automaton.cc \
gui.cc
gui.cc \
gui.moc.cc
## -------- ##
......
......@@ -24,23 +24,88 @@
#include <iostream>
#include "g_scene.hh"
#include "dialog_get_label.hh"
namespace gui
{
namespace display
{
GScene::GScene ()
: item_selected_(0)
: item_selected_(0),
transition_draft_(0),
transition_preview_(0),
preview_src_(0),
preserve_preview_(0)
{
}
void
GScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
GScene::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
mouse_pos_ = event->scenePos();
if (transition_draft_)
{
transition_draft_->refresh(event->scenePos());
}
this->QGraphicsScene::mouseMoveEvent(event);
}
void
GScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
if (!item_selected_ && event->button() == Qt::RightButton)
if (event->button() == Qt::RightButton)
{
emit addState(event->scenePos ());
// Create transition
if (preview_src_)
{
GState* state = dynamic_cast<GState*>(itemAt(event->scenePos()));
if (transition_preview_ && state)
{
QString str;
dialogs::DialogGetLabel dlg(&str);
// Prevent the preview from dissapearing when the state
// is deselected.
preserve_preview_ = true;
dlg.exec();
preserve_preview_ = false;
emit addTransition(preview_src_, state, str);
}
if (transition_draft_)
{
transition_draft_->deleteLater();
transition_draft_ = 0;
}
if (transition_preview_)
{
transition_preview_->deleteLater();
transition_preview_ = 0;
}
preview_src_ = 0;
event->accept();
return;
}
// Create state
if (!item_selected_)
{
event->accept();
emit addState(event->scenePos ());
return;
}
// Create transition preview
GState* state = dynamic_cast<GState*>(itemAt(event->scenePos()));
if (state)
{
preview_src_ = state;
transition_draft_ = new GTransitionDraft(*state, event->scenePos());
addItem(transition_draft_);
}
}
this->QGraphicsScene::mouseReleaseEvent(event);
}
void
GScene::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
this->QGraphicsScene::mousePressEvent(event);
}
......@@ -57,8 +122,6 @@ namespace gui
this, SLOT(itemSelected()));
connect(state, SIGNAL(deselected()),
this, SLOT(itemDeselected()));
connect(state, SIGNAL(addTransition(GState*, QString)),
this, SLOT(addTransition(GState*, QString)));
}
void
......@@ -77,6 +140,24 @@ namespace gui
void
GScene::delState()
{
GState* state = dynamic_cast<GState*>(sender());
// The source state for the transition preview is deleted:
// Cancel the preview.
if (state && state == preview_src_)
{
if (transition_draft_)
{
transition_draft_->deleteLater();
transition_draft_ = 0;
}
if (transition_preview_)
{
transition_preview_->deleteLater();
transition_preview_ = 0;
}
preview_src_ = 0;
}
emit delState(dynamic_cast<GState*>(sender()));
}
......@@ -98,13 +179,6 @@ namespace gui
emit delTransition(dynamic_cast<GTransition*>(sender()));
}
void
GScene::addTransition(GState* other, QString label)
{
emit addTransition(dynamic_cast<GState*>(sender()),
other, label);
}
void
GScene::setTransitionLabel(QString label)
{
......@@ -115,12 +189,57 @@ namespace gui
GScene::itemSelected()
{
item_selected_ += 1;
// Handle transition drawing
if (preview_src_)
{
GState* state = dynamic_cast<GState*>(sender());
if (state)
{
if (preserve_preview_)
return;
if (transition_preview_)
{
transition_preview_->deleteLater();
transition_preview_ = 0;
}
if (transition_draft_)
{
transition_draft_->deleteLater();
transition_draft_ = 0;
}
transition_preview_ = new GTransition(-1, *preview_src_, *state, "");
connectTransition(transition_preview_);
addItem(transition_preview_);
transition_preview_->select();
}
}
}
void
GScene::itemDeselected()
{
item_selected_ -= 1;
// Handle transition drawing
if (preview_src_)
{
GState* state = dynamic_cast<GState*>(sender());
if (state)
{
if (preserve_preview_)
return;
if (transition_preview_)
{
transition_preview_->deleteLater();
transition_preview_ = 0;
}
if (!transition_draft_)
{
transition_draft_ = new GTransitionDraft(*preview_src_, mouse_pos_);
addItem(transition_draft_);
}
return;
}
}
}
} // ! namespace display
......
......@@ -30,6 +30,7 @@
# include "common.hh"
# include "g_state.hh"
# include "g_transition.hh"
# include "g_transition_draft.hh"
namespace gui
{
......@@ -44,6 +45,8 @@ namespace gui
void connectState(GState* state);
void connectTransition(GTransition* transition);
void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
void mousePressEvent(QGraphicsSceneMouseEvent* event);
public slots:
......@@ -53,7 +56,6 @@ namespace gui
void setInitial(QString entry);
void setFinal(QString entry);
void setTransitionLabel(QString label);
void addTransition(GState* other, QString entry);
// Used to ignore right click events.
void itemSelected();
......@@ -72,6 +74,13 @@ namespace gui
private:
int item_selected_;
GTransitionDraft* transition_draft_;
GTransition* transition_preview_;
GState* preview_src_;
bool preserve_preview_;
QPointF mouse_pos_;
};
} // ! namespace display
......
......@@ -30,7 +30,6 @@
#include "g_state.hh"
#include "dialog_properties_state.hh"
#include "dialog_get_label.hh"
#include "common.hh"
......@@ -48,8 +47,6 @@ namespace gui
final_entry_ (final_entry),
index_ (index),
selected_ (false),
drawing_transition_ (false),
drawing_transition_enable_self_ (false),
looping_transitions_ (0)
{
setCursor (QCursor (Qt::ArrowCursor));
......@@ -66,6 +63,12 @@ namespace gui
label_ = str.str ().c_str ();
}
GState::~GState ()
{
if (selected_)
deselect();
}
void
GState::update_bounding_rect_()
{
......@@ -78,12 +81,6 @@ namespace gui
if (!final_entry_.isNull())
bounding_rect_ = bounding_rect_.united(QRectF(radius_, -radius_,
40, radius_));
if (drawing_transition_)
bounding_rect_ = bounding_rect_.united(QRectF(mouse_pos_.x() - 5,
mouse_pos_.y() - 5,
10,
10));
}
QRectF
......@@ -177,34 +174,6 @@ namespace gui
| Qt::AlignTop,
initial_entry_);
}
if (drawing_transition_)
{
painter->setPen("black");
painter->setBrush(QColor("black"));
QPainterPath path;
path.lineTo(mouse_pos_);
qreal dx = mouse_pos_.x ();
qreal dy = mouse_pos_.y ();
qreal d = std::sqrt ((double) (dx * dx + dy * dy));
if (d != 0)
{
QPointF c2 (mouse_pos_.x () - 8 * dx / d - 4 * dy / d,
mouse_pos_.y () - 8 * dy / d + 4 * dx / d);
QPointF c3 (mouse_pos_.x () - 8 * dx / d + 4 * dy / d,
mouse_pos_.y () - 8 * dy / d - 4 * dx / d);
path.lineTo (c2);
path.lineTo (c3);
path.lineTo (mouse_pos_);
}
painter->drawPath (path);
}
}
QVariant GState::itemChange (GraphicsItemChange,
......@@ -234,36 +203,12 @@ namespace gui
event->ignore();
return;
}
if (event->button () == Qt::RightButton)
{
drawing_transition_ = true;
drawing_transition_enable_self_ = false;
mouse_pos_ = event->pos();
update_bounding_rect_();
update();
return;
}
QGraphicsItem::mousePressEvent(event);
}
void
GState::mouseReleaseEvent (QGraphicsSceneMouseEvent* event)
{
if (drawing_transition_)
{
drawing_transition_ = false;
GState* s = dynamic_cast<GState*>(scene()->itemAt(event->scenePos()));
if (s && (s != this || drawing_transition_enable_self_))
{
QString str;
dialogs::DialogGetLabel dlg(&str);
dlg.exec();
emit addTransition(s, str);
}
update();
}
QGraphicsItem::mouseReleaseEvent(event);
}
......@@ -275,16 +220,6 @@ namespace gui
event->ignore();
return;
}
if (drawing_transition_)
{
event->ignore();
mouse_pos_ = event->pos();
if (qAbs(mouse_pos_.x()) + qAbs(mouse_pos_.y()) > radius_)
drawing_transition_enable_self_ = true;
update_bounding_rect_();
update();
return;
}
QGraphicsItem::mouseMoveEvent(event);
}
......
......@@ -45,6 +45,8 @@ namespace gui
QString initial_entry = 0,
QString final_entry = 0);
~GState();
QRectF boundingRect () const;
QPainterPath shape () const;
......@@ -93,8 +95,6 @@ namespace gui
inline int index () const;
inline bool is_drawing_transition() const;
public slots:
void refresh ();
void select ();
......@@ -111,8 +111,6 @@ namespace gui
void setInitial(QString entry);
void setFinal(QString entry);
void addTransition(GState* other, QString label);
private:
void update_bounding_rect_();
......@@ -139,11 +137,6 @@ namespace gui
// True if the state is selected
bool selected_;
// True if a transition is being drawn.
bool drawing_transition_;
bool drawing_transition_enable_self_;
QPointF mouse_pos_;
int looping_transitions_;
};
......
......@@ -103,12 +103,6 @@ namespace gui
return index_;
}
bool
GState::is_drawing_transition() const
{
return drawing_transition_;
}
} // ! namespace display
} // ! namespace gui
......
......@@ -82,6 +82,12 @@ namespace gui
refresh ();
}
GTransition::~GTransition()
{
if (selected_)
deselect();
}
QRectF
GTransition::boundingRect () const
{
......
......@@ -45,6 +45,8 @@ namespace gui
QString label,
int transition_index = 0);
~GTransition();
QRectF boundingRect () const;
QPainterPath shape () const;
......
// g_transition_draft.cc: this file is part of Vaucanson.
//
// Vaucanson, a generic library for finite state machines.
//
// Copyright (C) 2006 The Vaucanson Group.
//
// This program 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 2
// of the License, or (at your option) any later version.
//
// The complete GNU General Public Licence Notice can be found as the
// `COPYING' file in the root directory.
//
// The Vaucanson Group consists of people listed in the `AUTHORS' file.
//
/**
* @file g_state.hh
* @author Florent D'Halluin <d-halluin@lrde.epita.fr>
*
* FIXME
*/
#include "g_transition_draft.hh"
#include "common.hh"
#include <QCursor>
#include <iostream>
#include <cmath>
namespace gui
{
namespace display
{
GTransitionDraft::GTransitionDraft(GState& from,
QPointF to,
QString label)
: from_ (from),
to_ (to),
quad_point_distance_ (1),
label_point_distance_ (0.65),
angle_ (0),
default_color_ ("black"),
highlight_color_ (220, 30, 30),
color_ (default_color_),
label_ (label),
selected_ (false)
{
setCursor (QCursor (Qt::ArrowCursor));
setZValue(2);
QObject::connect (&from, SIGNAL(moved ()),
this, SLOT(refresh ()));
QObject::connect (&from, SIGNAL(destroyed ()),
this, SLOT(deleteLater ()));
refresh ();
}
GTransitionDraft::~GTransitionDraft()
{
if (selected_)
deselect();
}
QRectF
GTransitionDraft::boundingRect () const
{
BENCH_TASK_SCOPED("GTransitionDraft::boundingRect ()");
return bounding_rect_;
}
QPainterPath
GTransitionDraft::shape () const
{
BENCH_TASK_SCOPED("GTransitionDraft::shape ()");
return shape_;
}
void
GTransitionDraft::paint (QPainter *painter,
const QStyleOptionGraphicsItem *,
QWidget *)
{
BENCH_TASK_SCOPED("GTransitionDraft::paint ()");
painter->setPen (color_);
painter->drawPath (curve_);
painter->setBrush (color_);
painter->drawPath (arrow_);
painter->drawText ((int) label_point_.x () - LABEL_MAX_SIZE / 2,
(int) label_point_.y () - LABEL_MAX_SIZE / 2,
LABEL_MAX_SIZE, LABEL_MAX_SIZE,
Qt::AlignCenter, label_, &label_rect_);
// Update shape and bounding rect with the new
// label coordinates.
// FIXME: try to move this into refresh();
// Do not call prepareGeometryChange() here: kills perfs.
QPainterPath label;
label.addRect (label_rect_);
shape_ = label.united (curve_shape_);
bounding_rect_ = shape_.boundingRect ();
}
void
GTransitionDraft::refresh (QPointF to)
{
to_ = to;
refresh();
}
void
GTransitionDraft::refresh ()
{
BENCH_TASK_SCOPED("GTransitionDraft::refresh ()");
// Ensure proper indexing.
prepareGeometryChange();
// Hooks
float quad_point_distance_ = this->quad_point_distance_;
// Set temporary reference points
QPointF from = from_.scenePos();
QPointF to = to_;
qreal state_dx = to.x () - from.x ();
qreal state_dy = to.y () - from.y ();
// Compute quad point
quad_point_.setX ((to.x () + from.x ()) / 2
+ (state_dy) / 2 * quad_point_distance_);
quad_point_.setY ((to.y () + from.y ()) / 2
- (state_dx) / 2 * quad_point_distance_);