LayoutController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "../model/State.h"
25 #include "LayoutController.h"
27 
29 
30 #include <cassert>
31 #include <memory>
32 #include <utility>
33 
35  : QObject(),
36  idCounter(0),
37  layoutingDisabled(!startEnabled)
38 {
39  qRegisterMetaType<size_t>("size_t");
40  timer.setInterval(100);
41  connect(&timer, SIGNAL(timeout()), this, SLOT(startNextLayouting()), Qt::QueuedConnection);
42 
43  if (topState)
44  {
45  createMediator(topState);
46  }
47  else
48  {
49  // ARMARX_ERROR_S << "No state provided for constructor of LayoutController";
50  }
51 }
52 
54 {
55  //here (and not at the end of the function) because signals for the layout thread are queued.
56  //This garanties that the WorkerCreator first deletes all current states and then adds the
57  //worker for the new topState.
58  emit reset();
59 
60  mediators.clear();
61  states.clear();
62  idCounter = 0;
63 
64  createMediator(topState);
65  timer.start();
66 }
67 
69 {
70  for (auto med : mediators)
71  {
72  emit createWorker(med.second, med.first, med.second->getState()->getStateName());
73  }
74 }
75 
77 {
78  for (const auto& elem : mediators)
79  {
80  if (elem.second->getState().get() == state.get())
81  {
82  return elem.first;
83  }
84  }
85 
86  return -1;
87 }
88 
90 {
91  layoutingDisabled = !enable;
92 }
93 
94 void armarx::LayoutController::scheduleMediator(size_t mediatorId, bool layoutAll)
95 {
96  MediatorLayoutOptionPair correctPair(mediatorId, layoutAll);
97  MediatorLayoutOptionPair inversePair(mediatorId, !layoutAll);
98 
99  size_t count = layoutQueue.count(correctPair) + layoutQueue.count(inversePair);
100  assert(count <= 2);
101 
102  if (count == 0) //worker not yet scheduled
103  {
104  layoutQueue.append(correctPair);
105  }
106  else if (layoutAll && layoutQueue.contains(inversePair))
107  //worker is scheduled, but only supposed to layout edges
108  //but now it should also layout the nodes
109  {
110  layoutQueue.removeAll(inversePair);
111  layoutQueue.removeAll(correctPair);
112  layoutQueue.append(correctPair);
113  }
114 }
115 
116 bool armarx::LayoutController::layoutNow(size_t mediatorId, bool layoutAll)
117 {
118  auto iter = mediators.find(mediatorId);
119 
120  if (iter != mediators.end())
121  {
122  if (iter->second->getState()->getSubstates().size() > 0)
123  {
124  iter->second->startLayouting(layoutAll, 1);
125  return true;
126  }
127  return false;
128  }
129  else
130  {
131  ARMARX_ERROR_S << "Mediator with id " << mediatorId << " is scheduled but no mediator"
132  << " with this id could be found.";
133  return false;
134  }
135 }
136 
138 {
139  if (layoutingDisabled)
140  {
141  // ARMARX_INFO_S << "Layouting disabled!";
142  return;
143  }
144 
145  // ARMARX_WARNING_S << "Layouting activated";
146  timer.stop();
147  if (!(layoutQueue.empty()))
148  {
149  auto nextMediator = layoutQueue.takeFirst();
150  size_t mediatorId = nextMediator.first;
151  bool layoutAll = nextMediator.second;
152  if (!layoutNow(mediatorId, layoutAll))
153  {
154  QMetaObject::invokeMethod(this, "startNextLayouting");
155  }
156 
157  }
158  else
159  {
160  timer.start();
161  }
162 }
163 
165 {
166  //remove from layoutQueue
167  MediatorLayoutOptionPair truePair {mediatorId, true};
168 
169  while (layoutQueue.contains(truePair))
170  {
171  layoutQueue.removeAt(layoutQueue.indexOf(truePair));
172  }
173 
174  MediatorLayoutOptionPair falsePair {mediatorId, false};
175 
176  while (layoutQueue.contains(falsePair))
177  {
178  layoutQueue.removeAt(layoutQueue.indexOf(falsePair));
179  }
180 
181  //remove from states
182  auto iter = mediators.find(mediatorId);
183 
184  if (iter != mediators.end())
185  {
186  int statePos = states.indexOf(iter->second->getState());
187 
188  if (statePos != -1)
189  {
190  states.removeAt(statePos);
191  }
192 
193  //remove from mediators, destructor called by shared_ptr if necessary
194  mediators.erase(mediatorId);
195  }
196  else
197  {
198  ARMARX_INFO_S << "Mediator with id " << mediatorId << " was already deleted";
199  }
200 }
201 
203 {
204  if (signalType == statechartmodel::eAdded)
205  {
206  statechartmodel::StatePtr addedState = substate->getStateClass();
207 
208  if (addedState)
209  {
210  if (states.contains(addedState))
211  {
212  return;
213  }
214 
215  createMediator(addedState);
216  }
217  }
218 }
219 
220 void armarx::LayoutController::createMediator(armarx::statechartmodel::StatePtr state)
221 {
222  // ARMARX_INFO_S << "Creating mediator for state " << state->getStateName();
223  MediatorPtr mediator {new StateModelLayoutMediator(state, idCounter)};
224  idCounter++;
225 
226  qRegisterMetaType<statechartmodel::TransitionCPtr>("statechartmodel::TransitionCPtr");
227  qRegisterMetaType<statechartmodel::StateInstancePtr>("statechartmodel::StateInstancePtr");
228  qRegisterMetaType<statechartmodel::SignalType>("statechartmodel::SignalType");
229  qRegisterMetaType<SupportPoints>("SupportPoints");
230  qRegisterMetaType<QPointPtr>("QPointPtr");
231  qRegisterMetaType<FloatPtr>("FloatPtr");
232 
233  //state und mediator verbinden
234  bool correctConnected = connect(state.get(), SIGNAL(stateDeleted()),
235  mediator.get(), SLOT(stateDeleted()), Qt::QueuedConnection);
236 
237  if (!correctConnected)
238  {
239  ARMARX_ERROR_S << "Signal stateDeleted was not connected to slot stateDeleted of mediator";
240  }
241 
242  correctConnected = connect(state.get(), SIGNAL(substateChanged(statechartmodel::StateInstancePtr, statechartmodel::SignalType)),
243  mediator.get(), SLOT(substateChanged(statechartmodel::StateInstancePtr, statechartmodel::SignalType)), Qt::QueuedConnection);
244 
245  if (!correctConnected)
246  {
247  ARMARX_ERROR_S << "Signal substateChanged was not connected to slot substateChanged of mediator";
248  }
249 
250  correctConnected = connect(state.get(), SIGNAL(stateChanged(statechartmodel::SignalType)),
251  mediator.get(), SLOT(stateChanged(statechartmodel::SignalType)), Qt::QueuedConnection);
252 
253  if (!correctConnected)
254  {
255  ARMARX_ERROR_S << "Signal stateChanged was not connected to slot stateChanged of mediator";
256  }
257 
258  correctConnected = connect(state.get(), SIGNAL(transitionChanged(statechartmodel::TransitionCPtr, statechartmodel::SignalType)),
259  mediator.get(), SLOT(transitionChanged(statechartmodel::TransitionCPtr, statechartmodel::SignalType)), Qt::QueuedConnection);
260 
261  if (!correctConnected)
262  {
263  ARMARX_ERROR_S << "Signal transitionChanged was not connected to slot transitionChanged of mediator";
264  }
265 
266  correctConnected = connect(mediator.get(), SIGNAL(supportPointsChanged(statechartmodel::TransitionCPtr, SupportPoints, QPointPtr, FloatPtr)),
267  state.get(), SLOT(setTransitionSupportPoints(statechartmodel::TransitionCPtr, SupportPoints, QPointPtr, FloatPtr)), Qt::QueuedConnection);
268 
269  if (!correctConnected)
270  {
271  ARMARX_ERROR_S << "Signal supportPointsChanged of mediator"
272  << " was not connected to slot setTransitionSupportPoints";
273  }
274 
275  //Controller und mediator verbinden
276  correctConnected = connect(mediator.get(), SIGNAL(layoutingFinished()),
277  this, SLOT(startNextLayouting()), Qt::QueuedConnection);
278 
279  if (!correctConnected)
280  {
281  ARMARX_ERROR_S << "Signal layoutingFinished of mediator"
282  << " was not connected to slot startNextLayouting of controller";
283  }
284 
285  correctConnected = connect(mediator.get(), SIGNAL(deleteMe(size_t)),
286  this, SLOT(deleteMediator(size_t)), Qt::QueuedConnection);
287 
288  if (!correctConnected)
289  {
290  ARMARX_ERROR_S << "Signal deleteMe of mediator"
291  << " was not connected to slot deleteMediator of controller";
292  }
293 
294  correctConnected = connect(mediator.get(), SIGNAL(scheduleMe(size_t, bool)),
295  this, SLOT(scheduleMediator(size_t, bool)));
296 
297  if (!correctConnected)
298  {
299  ARMARX_ERROR_S << "Signal scheduleMe of mediator"
300  << " was not connected to slot scheduleMediator of controller";
301  }
302 
303  correctConnected = connect(mediator.get(), SIGNAL(substateFound(statechartmodel::StateInstancePtr, statechartmodel::SignalType)),
304  this, SLOT(potentialStateAdded(statechartmodel::StateInstancePtr, statechartmodel::SignalType)), Qt::QueuedConnection);
305 
306  if (!correctConnected)
307  {
308  ARMARX_ERROR_S << "Signal substateFound of mediator"
309  << " was not connected to slot potentialStateAdded of controller";
310  }
311 
312  //controller und state verbinden
313  correctConnected = connect(state.get(), SIGNAL(substateChanged(statechartmodel::StateInstancePtr, statechartmodel::SignalType)),
314  this, SLOT(potentialStateAdded(statechartmodel::StateInstancePtr, statechartmodel::SignalType)), Qt::QueuedConnection);
315 
316  if (!correctConnected)
317  {
318  ARMARX_ERROR_S << "Signal substateChanged of state was not connected to slot"
319  << " potentialStateAdded of controller";
320  }
321 
322  mediators.insert(std::pair<size_t, MediatorPtr>(mediator -> getID(), mediator));
323  states.push_back(state);
324 
325  emit createWorker(mediator, mediator->getID(), state->getStateName());
326  QMetaObject::invokeMethod(this, "scheduleMediator", Qt::QueuedConnection, Q_ARG(size_t, mediator->getID()), Q_ARG(bool, true));
327 }
armarx::StateModelLayoutMediator
Definition: StateModelLayoutMediator.h:50
armarx::MediatorLayoutOptionPair
std::pair< size_t, bool > MediatorLayoutOptionPair
Definition: LayoutController.h:43
armarx::LayoutController::potentialStateAdded
void potentialStateAdded(statechartmodel::StateInstancePtr substate, statechartmodel::SignalType signalType)
potentialStateAdded If a substate is added it might mean that there is a new state needing a LayoutWo...
Definition: LayoutController.cpp:202
armarx::LayoutController::LayoutController
LayoutController(armarx::statechartmodel::StatePtr topState, bool startEnabled=true)
Definition: LayoutController.cpp:34
armarx::FloatPtr
std::shared_ptr< float > FloatPtr
Definition: Transition.h:40
armarx::LayoutController::setTopState
void setTopState(statechartmodel::StatePtr topState)
setTopState Resets all workers i.e.
Definition: LayoutController.cpp:53
StateModelLayoutMediator.h
armarx::statechartmodel::StateInstancePtr
std::shared_ptr< StateInstance > StateInstancePtr
Definition: StateInstance.h:138
armarx::QPointPtr
std::shared_ptr< QPointF > QPointPtr
Definition: Transition.h:41
armarx::LayoutController::startNextLayouting
void startNextLayouting()
startNextLayouting The last worker that layouted is finished and the next should be started.
Definition: LayoutController.cpp:137
armarx::LayoutController::createAllWorkers
void createAllWorkers()
createAllWorkers Creates workers for all mediators
Definition: LayoutController.cpp:68
LayoutController.h
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:209
armarx::LayoutController::scheduleMediator
void scheduleMediator(size_t mediatorId, bool layoutAll)
scheduleMediator Put the mediator in the layoutQueue.
Definition: LayoutController.cpp:94
armarx::LayoutController::getStateId
size_t getStateId(armarx::statechartmodel::StatePtr state) const
Definition: LayoutController.cpp:76
armarx::statechartmodel::eAdded
@ eAdded
Definition: SignalType.h:35
armarx::LayoutController::layoutNow
bool layoutNow(size_t mediatorId, bool layoutAll)
Definition: LayoutController.cpp:116
armarx::MediatorPtr
std::shared_ptr< StateModelLayoutMediator > MediatorPtr
Definition: LayoutController.h:41
armarx::statechartmodel::SignalType
SignalType
The SignalType enum.
Definition: SignalType.h:33
armarx::statechartmodel::TransitionCPtr
std::shared_ptr< const Transition > TransitionCPtr
Definition: Transition.h:94
armarx::statechartmodel::StatePtr
std::shared_ptr< State > StatePtr
Definition: State.h:46
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:195
Logging.h
armarx::LayoutController::deleteMediator
void deleteMediator(size_t mediatorId)
deleteMediator Call the destructor of mediator and tell LayoutWorkerCreator to delete the correspondi...
Definition: LayoutController.cpp:164
armarx::LayoutController::enableLayouting
void enableLayouting(bool enable=true)
Definition: LayoutController.cpp:89