/* AADL plugin for DIA
*
* Copyright (C) 2005 Laboratoire d'Informatique de Paris 6
* Author: Pierre Duquesne
*
* 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <assert.h>
#include <math.h>
#include <string.h>

#include "intl.h"
#include "object.h"
#include "element.h"
#include "diarenderer.h"
#include "attributes.h"
#include "text.h"
#include "properties.h"

#undef min
#define min(a,b) (a<b?a:b)
#undef max
#define max(a,b) (a>b?a:b)

#define L1 printf("%d\n", __LINE__);


/***********************************************
 **              CONSTANTS                    **
 ***********************************************/

static const double AADLBOX_BORDERWIDTH = 0.1;
static const double AADLBOX_FONTHEIGHT = 0.8;
static const double AADLBOX_TEXT_MARGIN = 0.5;

#define AADL_PORT_MAX_OUT 1.0  /* Maximum size out of the box */

#define AADL_MEMORY_FACTOR 0.1
#define AADLBOX_INCLINE_FACTOR 0.2
#define AADLBOX_DASH_LENGTH 0.3
#define AADL_BUS_ARROW_SIZE_FACTOR 0.16
#define AADL_BUS_HEIGHT_FACTOR 0.3
#define AADL_ROUNDEDBOX_CORNER_SIZE_FACTOR 0.25

/***********************************************
 **                  TYPES                    **
 ***********************************************/

typedef struct _Aadlport Aadlport;
typedef struct _Aadlbox Aadlbox;

typedef struct _Aadlbox_specific Aadlbox_specific;


struct _Aadlbox
{
  Element element;

  gchar *declaration;
  
  Text *name;
  TextAttributes attrs;

  int num_ports;
  Aadlport **ports;

  int num_connections;
  ConnectionPoint **connections;

  Color line_color;
  Color fill_color;

  Aadlbox_specific *specific;
};


typedef enum {
  BUS,
  DEVICE,
  MEMORY,
  PROCESSOR,
  PROCESS,
  SUBPROGRAM,
  SYSTEM,
  THREAD,
  THREAD_GROUP,
  
  ACCESS_PROVIDER,
  ACCESS_REQUIRER,
  IN_DATA_PORT,
  IN_EVENT_PORT,
  IN_EVENT_DATA_PORT,
  OUT_DATA_PORT,
  OUT_EVENT_PORT,
  OUT_EVENT_DATA_PORT,
  IN_OUT_DATA_PORT,
  IN_OUT_EVENT_PORT,
  IN_OUT_EVENT_DATA_PORT,
  
  PORT_GROUP
} Aadl_type;


struct _Aadlport {
  Aadl_type type;
  Handle *handle;
  real angle;

  ConnectionPoint in;
  ConnectionPoint out;

  gchar *declaration;
};

typedef void (*AadlProjectionFunc) (Aadlbox *aadlbox,Point *p,real *angle);
typedef void (*AadlDrawFunc) (Aadlbox* obj, DiaRenderer* ddisp);
typedef void (*AadlTextPosFunc) (Aadlbox* obj, Point *p);
typedef void (*AadlSizeFunc) (Aadlbox* obj, Point *size);

/* In the abstract class system (see aadlbox.c), these are the 
   functions an inherited class *must* define, because they are 
   used by aadlbox_ functions   */

struct _Aadlbox_specific
{
  AadlProjectionFunc project_point_on_nearest_border;
  AadlTextPosFunc text_position;
  AadlSizeFunc min_size;
};


/***********************************************
 **                 FUNCTIONS                 **
 ***********************************************/


/* aadltext.c */
void aadldata_text_position(Aadlbox *aadlbox, Point *p);
void aadldata_minsize(Aadlbox *aadlbox, Point *size);

void aadlprocess_text_position(Aadlbox *aadlbox, Point *p);
void aadlprocess_minsize(Aadlbox *aadlbox, Point *size);

void aadlbus_text_position(Aadlbox *aadlbox, Point *p);
void aadlbus_minsize(Aadlbox *aadlbox, Point *size);

void aadlsystem_text_position(Aadlbox *aadlbox, Point *p);
void aadlsystem_minsize(Aadlbox *aadlbox, Point *size);

void aadlsubprogram_text_position(Aadlbox *aadlbox, Point *p);
void aadlsubprogram_minsize(Aadlbox *aadlbox, Point *size);

void aadlmemory_text_position(Aadlbox *aadlbox, Point *p);
void aadlmemory_minsize(Aadlbox *aadlbox, Point *size);

/* aadlport.c */
void rotate_around_origin (Point *p, real angle);
void aadlbox_draw_port(Aadlport *port, DiaRenderer *renderer);
void aadlbox_update_port(Aadlbox *aadlbox, Aadlport *port);
void aadlbox_update_ports(Aadlbox *aadlbox);

/* aadlbox.c */
real aadlbox_distance_from(Aadlbox *aadlbox, Point *point);
void aadlbox_select(Aadlbox *aadlbox, Point *clicked_point,
		    DiaRenderer *interactive_renderer);
ObjectChange* aadlbox_move_handle(Aadlbox *aadlbox, Handle *handle,
				  Point *to, ConnectionPoint *cp,
				  HandleMoveReason reason, 
				  ModifierKeys modifiers);
ObjectChange* aadlbox_move(Aadlbox *aadlbox, Point *to);
void aadlbox_draw(Aadlbox *aadlbox, DiaRenderer *renderer);
DiaObject *aadlbox_create(Point *startpoint, void *user_data,
			  Handle **handle1, Handle **handle2);
void aadlbox_destroy(Aadlbox *aadlbox);
PropDescription *aadlbox_describe_props(Aadlbox *aadlbox);
void aadlbox_get_props(Aadlbox *aadlbox, GPtrArray *props);
void aadlbox_set_props(Aadlbox *aadlbox, GPtrArray *props);
DiaObject *aadlbox_copy(DiaObject *obj);
DiaMenu * aadlbox_get_object_menu(Aadlbox *aadlbox, Point *clickedpoint);
void aadlbox_save(Aadlbox *aadlbox, ObjectNode obj_node, const char *filename);
void aadlbox_load(ObjectNode obj_node, int version, const char *filename,
			Aadlbox *aadlbox);

/* aadldata.c */
void aadlbox_project_point_on_rectangle(Rectangle *rectangle,
					Point *p,real *angle);
 void aadldata_project_point_on_nearest_border(Aadlbox *aadlbox, 
 					 Point *p,real *angle); 

/* aadlprocess.c */

void
aadlbox_inclined_project_point_on_nearest_border(Aadlbox *aadlbox,Point *p,
						 real *angle);
void aadlprocess_text_position(Aadlbox *aadlbox, Point *p);
real aadlprocess_blank_space_height(Aadlbox *aadlbox);
real aadlprocess_blank_space_width(Aadlbox *aadlbox);

/* aadlthread.c */
void aadlbox_draw_inclined_box(Aadlbox *aadlbox, DiaRenderer *renderer,
				      LineStyle linestyle);
/* aadlsubprogram.c */
void
aadlsubprogram_project_point_on_nearest_border(Aadlbox *aadlbox,Point *p,
					       real *angle);
/* aadlsystem.c */
void aadlbox_draw_rounded_box (Aadlbox *aadlbox, DiaRenderer *renderer,
			       LineStyle linestyle);


