Logo Search packages:      
Sourcecode: magics++ version File versions  Download package

ViewNode.cc

Go to the documentation of this file.
/******************************** LICENSE ********************************

 Copyright 2007 European Centre for Medium-Range Weather Forecasts (ECMWF)

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at 

    http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

 ******************************** LICENSE ********************************/

/*! \file ViewNode.cc
    \brief Implementation of the Template class ViewNode.
    
    Magics Team - ECMWF 2007
    
    Started: Tue 6-Mar-2007
    
    Changes:
    
*/

#include "ViewNode.h"
#include "Transformation.h"
#include "Dimension.h"
#include "Layout.h"

#include "SceneVisitor.h"
#include "LegendVisitor.h"
#include "TextVisitor.h"
#include "MetaData.h"

#include "AnimationRules.h"

using namespace magics;

ViewNode::ViewNode() : transformation_(0), textVisitor_(0), legendVisitor_(0)
{
      static int i = 0;
      ostringstream n;
      n << "ViewNode" << i;
      name_ = n.str();
      i++;
      layout_ = new Layout();
      layout_->name(name_);
} 


ViewNode::~ViewNode() 
{
}

void ViewNode::text(TextVisitor* text)
{
      textVisitor_.push_back(text);
      ((BasicSceneObject*)text)->parent(this);
}
void ViewNode::legend(LegendVisitor* legend)
{
      legendVisitor_ = legend;
      //legend->parent((BasicSceneNode*)this);
}

void ViewNode::visit(MetaDataVisitor& metadata)
{

      double top = 0;
      double left = 0;
      double width = 200;
      double height = 100;
      
      
      drawing_->getDriverInfo(left, top, width, height);
      top = 0;
      left = 0;
            
      
      
   
      //Log::dev()<< *drawing_ << endl;

      ViewNode::transformation_->visit(metadata, left, top, width, height);
      
      
      

      BasicSceneObject::visit(metadata);
      for (vector<TextVisitor*>::iterator text = texts_.begin(); text != texts_.end(); ++text ) 
                  (*text)->visit(metadata);
      
}

/*!
 Class information are given to the output-stream.
*/          
void ViewNode::print(ostream& out)  const
{
      out << "ViewNode[";
      out << "]";
}

void ViewNode::getReady()
{
      Log::dev() << " ViewNode::getReady() \n";
      BasicSceneObject::getReady();
}

void ViewNode::visit(PreviewVisitor& preview) 
{
      preview.minX(ViewNode::transformation_->getMinPCX());
      preview.maxX(ViewNode::transformation_->getMaxPCX());
      preview.minY(ViewNode::transformation_->getMinPCY());
      preview.maxY(ViewNode::transformation_->getMaxPCY());
      
      dispatch(preview);
      
}

Layout* ViewNode::execute(AnimationStep& step,  Layout& visitor)
{
      
      vector<Layout*>::const_iterator component = components_.begin();
      Layout*  layout = 0;
      while ( layout == 0 && component != components_.end() ) {
            layout = visitor.execute(step, *component);
          ++component;
      }
      return layout;
}
      

void ViewNode::buildLayout(Layout& parent, ViewNode& from)
{
      LayoutHelper helper;
      drawing_ = new DrawingVisitor();
      
      parent.push_back(drawing_);
      double width = 100-drawing_left_-drawing_right_;
      double height = 100-drawing_top_-drawing_bottom_;
      double haxis = 100/absoluteHeight() *0.75;
      double vaxis = 100/absoluteWidth() *1.25;
      drawing_->transformation(ViewNode::transformation_);
            drawing_->y(drawing_bottom_);
            drawing_->x(drawing_left_);
            drawing_->height(height);
            drawing_->width(width);
            drawing_->id(id_);
            drawing_->zoomable(true);
            drawing_->zoomLevels(zoomLevels_);
            drawing_->zoomCurrentLevel(zoomCurrentLevel_);
            drawing_->frame(*layout_);
            drawing_->frameIt();
            components_.push_back(drawing_);

            
            helper.add(drawing_);
                  // Then the axis! 
                leftAxis_ = new LeftAxisVisitor(*drawing_);
                  parent.push_back(leftAxis_);        
                  leftAxis_->width(vaxis);
                  leftAxis_->frameIt();
                  components_.push_back(leftAxis_);
                
                  helper.attachLeft(leftAxis_);
                
                  rightAxis_ = new RightAxisVisitor(*drawing_);
                  parent.push_back(rightAxis_);             
                  rightAxis_->width(vaxis);
                  rightAxis_->frameIt();
                  helper.attachRight(rightAxis_);
                  components_.push_back(rightAxis_);
               
                  topAxis_ = new TopAxisVisitor(*drawing_);
                  parent.push_back(topAxis_);
                  topAxis_->height(haxis);
                  topAxis_->frameIt();                
                  helper.attachTop(topAxis_);
                  components_.push_back(topAxis_);
                  
                  bottomAxis_ = new BottomAxisVisitor(*drawing_);
                  parent.push_back(bottomAxis_);
                  bottomAxis_->height(haxis);               
                  bottomAxis_->frameIt();
                  components_.push_back(bottomAxis_);
                  helper.attachBottom(bottomAxis_);
                  
                  helper.add(topAxis_);
                  helper.add(leftAxis_);
                  helper.add(rightAxis_);
                  
                  if ( from.legendVisitor_) {
                        legend_ = from.legendVisitor_->clone(); 
                        parent.push_back(legend_);    
                        ((BasicSceneObject*)legend_)->orphan();
                        ((BasicSceneObject*)legend_)->parent(this);
                        if ( !legend_ ->positional() ) {
                              
                              legend_->height(5);
                              helper.attachTop(legend_);
                              legend_->x(drawing_left_);                                  
                              legend_->width(100-drawing_left_-drawing_right_);
                              helper.add(legend_);
                        }
                        else {
                              legend_->getReady();
                        }
                        components_.push_back(legend_);
                        //legend_->frameIt();                           
                        
                        
                  }
                  else 
                        legend_ = 0;
                  
                  texts_.clear();
                  for (vector<TextVisitor*>::iterator text = from.textVisitor_.begin(); text != from.textVisitor_.end(); ++text ) {             
                        ((BasicSceneObject*)(*text))->orphan();
                        ((BasicSceneObject*)(*text))->parent(this);
                  
                        texts_.push_back(*text);
                        components_.push_back(*text);
                        
                        if ( !texts_.back()->positional() ) {
                              texts_.back()->height(10);
                              helper.attachNoConstraintTop(texts_.back());
                        }                 
                        else {
                              texts_.back()->getReady();
                        }
                        texts_.back()->frameIt();
                  }
                  
            
                  
                  magnify_ = new MagnifierVisitor();
                  
                  magnify_->owner(this);
                  
                  parent.push_back(magnify_);
                  magnify_->transformation(ViewNode::transformation_);
                  
                  magnify_->y(drawing_bottom_);
                  magnify_->x(drawing_left_);
                  magnify_->height(100-drawing_top_-drawing_bottom_);
                  magnify_->width(100-drawing_left_-drawing_right_);
      
}



void ViewNode::copy(const ViewNode& other)
{
      transformation_ = other.transformation_;
      drawing_bottom_ = other.drawing_bottom_;
      drawing_top_ = other.drawing_top_;
      drawing_left_ = other.drawing_left_;
      drawing_right_ = other.drawing_right_;
      layout_->frame(*other.layout_);
      
}


class SlideViewNode : public ViewNode {
public:
      SlideViewNode(ViewNode& parent, AnimationStep* step) : parent_(parent), step_(step) { copy(parent_); }
      ~SlideViewNode() {}

      ViewNode& parent_;
      AnimationStep* step_;
      
      void visit(BasicGraphicsObjectContainer& tree) {
            
            tree.push_back(layout_);
            cout << *this << endl;
            buildLayout(*layout_, parent_);
            if (legend_) 
                  step_->visit(*legend_);

            step_->visit(*drawing_);
            for (vector<TextVisitor*>::const_iterator text = texts_.begin(); text != texts_.end(); ++text ) {
                  Layout* layout = (*text)->execute(*step_,  *text);
                  //layout is is a clone of the initial textvisitor!
                layout->orphan();
                  // WE attach it to the layout!
              
                layout_->push_back(layout);
                cout << *layout << endl;
            }
                  
                  
            
            drawing_->visit(parent_);
            topAxis_->visit(parent_);     
            bottomAxis_->visit(parent_);
            leftAxis_->visit(parent_);
            rightAxis_->visit(parent_);
                  
            drawing_->frameIt();
      }
      void resolve() {}
      
      
            
};

void ViewNode::resolve() {
      // First the info about the animation overlay! 
      AsIsAnimationRules* rules = new AsIsAnimationRules(*this);
      BasicSceneObject::visit(*rules);
            
      layout_->animationRules(rules);     
      Log::dev() << *rules << endl;
      // Here we are going to update the Magics Tree!  
      // Now the layout of the node not the number of slides and the contains of each slide! 
      for ( vector<AnimationStep*>::iterator step = rules->begin(); step != rules->end(); ++step) {
            SlideViewNode* node = new SlideViewNode(*this, *step);
            this->parent_->insert(node);
      }
      
}

void ViewNode::visit(BasicGraphicsObjectContainer& tree)
{
      Log::dev() << " ViewNode::visit(GraphicsList&) \n";
      
      
      BasicSceneObject::visit(*ViewNode::transformation_); // to set up the automatic style for mapping! 
      
      
      tree.push_back(layout_);
      
      // First the info about the animation overlay! 
      AsIsAnimationRules* rules = new AsIsAnimationRules(*this);
      BasicSceneObject::visit(*rules);
      
      layout_->animationRules(rules);
      
      
      buildLayout(*layout_, *this);
      
      drawing_->visit(*this);
      topAxis_->visit(*this); 
      bottomAxis_->visit(*this);
      leftAxis_->visit(*this);
      rightAxis_->visit(*this);
      
      PreviewVisitor* preview = new PreviewVisitor();
      layout_->push_back(preview);
      preview->transformation(ViewNode::transformation_);
      
      
      preview->height(100-drawing_top_-drawing_bottom_);
      preview->width(100-drawing_left_-drawing_right_);
      preview->visit(*this);
      
      
      if (legend_) 
                  legend_->visit(*this);
      for (vector<TextVisitor*>::iterator text = texts_.begin(); text != texts_.end(); ++text ) {
                  (*text)->visit(*layout_);
                  
      }

      // Now use the visitors!!! ( could be metada, preview...)
      for (vector<SceneVisitor*>::iterator  visitor = visitors_.begin(); visitor != visitors_.end(); ++visitor ) {
            (*visitor)->visit(*layout_); // in case the visitor has some object to acch to the graphical tree
            (*visitor)->visit(*this);
      }
      
      
      
      drawing_->frameIt();
      
      for ( vector<BasicSceneObject*>::iterator item = items_.begin(); item != items_.end(); ++item) 
                                          (*item)->visit(*layout_); 
      
}



XmlViewNode::XmlViewNode()
{
      //displayType_ = INLINE;
}

XmlViewNode::~XmlViewNode()
{
}



void XmlViewNode::getReady()
{
      assert (parent_);
      ViewNode::transformation_ = XmlViewNodeAttributes::transformation_.get();     
      
      Dimension bottom(bottom_, parent_->absoluteHeight(), 0);
      Dimension left(left_, parent_->absoluteWidth(), 0);
      Dimension width(XmlBasicNodeAttributes::width_, parent_->absoluteWidth(), 100);
      Dimension height(XmlBasicNodeAttributes::height_, parent_->absoluteHeight(), 100);
      
      
      
      Dimension mb(margin_bottom_, height.absolute(), 5);
      Dimension ml(margin_left_, width.absolute(), 7.5);
      Dimension mr(margin_right_, width.absolute(), 7.5);
      Dimension mt(margin_top_, height.absolute(), 10);
      
      drawing_bottom_ = mb.percent();
    drawing_left_ = ml.percent();
      drawing_right_ = mr.percent();
      drawing_top_ = mt.percent();



      double wab =  width.absolute()  - mr.absolute() - ml.absolute();
      double hab =  height.absolute()  - mt.absolute() - mb.absolute();

      double waa = wab;
      double haa = hab;
      Log::dev() << "befor aspect ratio -->[" << waa << ", " << haa << "]" << endl; 
      
      Log::dev() << "after aspect ratio -->[" << waa << ", " << haa << "]" << endl; 
      
      // could be usefull if we want to add the option compressed layout! 
      //double w1 = (waa + mr.absolute() + ml.absolute()) / absoluteWidth() *100;
      //double h1 = (haa +  mt.absolute() + mb.absolute()) / absoluteHeight() *100;
      
      double w2 = 100;
      double h2 =100;
      
      if ( fitted_  == "expand" ) {
            ViewNode::transformation_->fill(waa, haa);
            
            absoluteRootHeight(haa);
            absoluteRootWidth(waa); 
      }
      if ( fitted_  == "crop" ) {
            ViewNode::transformation_->aspectRatio(waa, haa);
            absoluteRootWidth(waa); 
            absoluteRootHeight(haa);
      }
      else {
            ViewNode::transformation_->aspectRatio(waa, haa);
             w2 = waa / width.absolute() *100;
             h2 = haa / height.absolute() *100;
      }
      
      
      drawing_bottom_ = 100 - drawing_top_ - h2;      
      drawing_right_ = 100 - drawing_left_- w2;
      layout_->x(left.percent());
      layout_->y(bottom.percent());
            
      
      layout_->width(width.percent());
      layout_->height(height.percent());
      layout_->display(display_);   
      layout_->frame(true, border_, *border_colour_, border_style_, border_thickness_);

      
      BasicSceneObject::getReady();
      
}

void XmlViewNode::print(ostream&) const
{
}




FortranViewNode::FortranViewNode()
{
}

FortranViewNode::~FortranViewNode()
{
}




#define undef(x) x ==-1


class AdjustHelper
{
public:
      AdjustHelper(double top, double bottom, double height, double parent) : 
            top_(top), bottom_(bottom), height_(height), parent_(parent) {}
      ~AdjustHelper() {}
      void operator()(double& top, double& bottom, double& height) {
            if ( undef(top)  ) { 
                  if ( undef(bottom) ) {
                        if ( undef(height) ) {
                              height = height_;
                              bottom = bottom_;
                              top = top_;
                        }
                        else { // we adjust to the top!
                              top = top_;
                              height = height / parent_ *100;
                              bottom = 100-top-height;
                        }
                  }
                  else { // bottom is defined
                        if ( undef(height) ) {
                              bottom = bottom / parent_ *100;
                              top = top_;
                              height=100-bottom-top;
                        }
                        else { // we adjust to the top!
                              bottom = bottom / parent_ *100;
                              height=height / parent_ *100;
                              top=100 -height-bottom;
                        }                 
                  } 
            }
            else { // Top is defined 
                  if ( undef(bottom) ) {
                              if ( undef(height) ) {
                                    top = top / parent_*100;
                                    bottom = bottom_;
                                    height = 100-top-bottom;
                              }
                              else {
                                    top = top / parent_ *100;
                                    height = height / parent_ *100;
                                    bottom = 100 -top-height;
                              }
                        }
                        else { // bottom is defined
                              if ( undef(height) ) {
                                     top = top / parent_ *100;
                                     bottom = bottom / parent_ *100;                                   
                                     height=100-bottom-top;
                              }
                              else { 
                                    top = top / parent_ *100;
                                    bottom = bottom / parent_ *100;
                                    height=height / parent_ *100;
                              }                 
                        }           
            }
}
protected:
      double top_;
      double bottom_;
      double height_;
      double parent_;
};

void FortranViewNode::getReady()
{
      assert (parent_);
      
      ViewNode::transformation_ = FortranViewNodeAttributes::transformation_.get();
//    Log::dev()<< *ViewNode::transformation_ << endl;
      double left =  FortranViewNodeAttributes::left_;
      double right =  FortranViewNodeAttributes::right_;
      double top =  FortranViewNodeAttributes::top_;
      double bottom =  FortranViewNodeAttributes::bottom_;
      double width = FortranViewNodeAttributes::width_;     
      double height = FortranViewNodeAttributes::height_;
      
      AdjustHelper vertical(20, 5, 70,  parent_->absoluteHeight());
      AdjustHelper horizontal(7.5, 7.5, 85,  parent_->absoluteWidth());
      
      vertical(top, bottom, height);
      horizontal(left, right, width);
      
      double abswidth = width * absoluteWidth()  / 100;
      double absheight =  height * absoluteHeight()  / 100;
      
      Log::dev() << "[" << abswidth << ", " << absheight << "]" << endl;
      Log::dev() << "[" << width << ", " << height << "]" << endl;
      


      ViewNode::transformation_->aspectRatio(abswidth, absheight);
      Log::dev() << "after aspect ratio -->[" << abswidth << ", " << absheight << "]" << endl; 
      Log::dev() << "[" << abswidth << ", " << absheight << "]" << endl;
      Log::dev() << "[" << absoluteWidth() << ", " << absoluteWidth() << "]" << endl;
      
      
      
      width = abswidth / absoluteWidth() *100;
      height = absheight / absoluteHeight() *100;
      
      
      Log::dev() << "[" << width << ", " << height << "]" << endl;
      // This is for alignement.. need further test!
      double x = magCompare(horizontal_, "left") ?  left : 100 - left - width;
      double y = magCompare(vertical_, "bottom") ?  bottom : 100  - top - height;
      
            

            

      drawing_top_ = 100 - y - height;
      drawing_bottom_= y;
      drawing_right_ = 100 - x - width;
      drawing_left_ = x;
      
      layout_->frame(true, frame_, *frame_colour_, frame_line_style_, frame_thickness_);

      BasicSceneObject::getReady();
}

void FortranViewNode::print(ostream& out) const
{
      out << "FortranViewNode[";
      BasicSceneObject::print(out);
      FortranViewNodeAttributes::print(out);
      out << "]";
}

BasicSceneNode* FortranViewNode::clone()
{
      FortranViewNode* node = new FortranViewNode();
      //node->copy(*this);
      return node;
}


Generated by  Doxygen 1.6.0   Back to index