static void box_update_data(Box *box, AnchorShape horiz, AnchorShape vert) { Element *elem = &box->element; ElementBBExtras *extra = &elem->extra_spacing; DiaObject *obj = &elem->object; Point center, bottom_right; Point p; real radius; real width, height; /* save starting points */ center = bottom_right = elem->corner; center.x += elem->width/2; bottom_right.x += elem->width; center.y += elem->height/2; bottom_right.y += elem->height; text_calc_boundingbox(box->text, NULL); width = box->text->max_width + box->padding*2 + box->border_width; height = box->text->height * box->text->numlines + box->padding*2 + box->border_width; /* * If elem->width (e.g. the new requested dimensions of this object * from move_handle()) is smaller than the minimum width (i.e. the * width calculated from text-width, padding and border), then * set the width to the minimum. Or else;) */ if (box->text_fitting != TEXTFIT_NEVER) { if ( box->text_fitting == TEXTFIT_ALWAYS || width > elem->width) elem->width = width; if ( box->text_fitting == TEXTFIT_ALWAYS || height > elem->height) elem->height = height; } /* move shape if necessary ... */ switch (horiz) { case ANCHOR_MIDDLE: elem->corner.x = center.x - elem->width/2; break; case ANCHOR_END: elem->corner.x = bottom_right.x - elem->width; break; default: break; } switch (vert) { case ANCHOR_MIDDLE: elem->corner.y = center.y - elem->height/2; break; case ANCHOR_END: elem->corner.y = bottom_right.y - elem->height; break; default: break; } p = elem->corner; p.x += elem->width / 2.0; p.y += elem->height / 2.0 - box->text->height * box->text->numlines / 2 + box->text->ascent; switch (box->text->alignment) { case ALIGN_LEFT: p.x -= (elem->width - box->padding*2 + box->border_width)/2; break; case ALIGN_RIGHT: p.x += (elem->width - box->padding*2 + box->border_width)/2; break; case ALIGN_CENTER: break; } text_set_position(box->text, &p); radius = box->corner_radius; radius = MIN(radius, elem->width/2); radius = MIN(radius, elem->height/2); radius *= (1-M_SQRT1_2); /* Update connections: */ connpoint_update(&box->connections[0], elem->corner.x + radius, elem->corner.y + radius, DIR_NORTHWEST); connpoint_update(&box->connections[1], elem->corner.x + elem->width / 4.0, elem->corner.y, DIR_NORTH); connpoint_update(&box->connections[2], elem->corner.x + elem->width / 2.0, elem->corner.y, DIR_NORTH); connpoint_update(&box->connections[3], elem->corner.x + elem->width * 3.0 / 4.0, elem->corner.y, DIR_NORTH); connpoint_update(&box->connections[4], elem->corner.x + elem->width - radius, elem->corner.y + radius, DIR_NORTHEAST); connpoint_update(&box->connections[5], elem->corner.x, elem->corner.y + elem->height / 4.0, DIR_WEST); connpoint_update(&box->connections[6], elem->corner.x + elem->width, elem->corner.y + elem->height / 4.0, DIR_EAST); connpoint_update(&box->connections[7], elem->corner.x, elem->corner.y + elem->height / 2.0, DIR_WEST); connpoint_update(&box->connections[8], elem->corner.x + elem->width, elem->corner.y + elem->height / 2.0, DIR_EAST); connpoint_update(&box->connections[9], elem->corner.x, elem->corner.y + elem->height * 3.0 / 4.0, DIR_WEST); connpoint_update(&box->connections[10], elem->corner.x + elem->width, elem->corner.y + elem->height * 3.0 / 4.0, DIR_EAST); connpoint_update(&box->connections[11], elem->corner.x + radius, elem->corner.y + elem->height - radius, DIR_SOUTHWEST); connpoint_update(&box->connections[12], elem->corner.x + elem->width / 4.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&box->connections[13], elem->corner.x + elem->width / 2.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&box->connections[14], elem->corner.x + elem->width * 3.0 / 4.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&box->connections[15], elem->corner.x + elem->width - radius, elem->corner.y + elem->height - radius, DIR_SOUTHEAST); connpoint_update(&box->connections[16], elem->corner.x + elem->width / 2, elem->corner.y + elem->height / 2, DIR_ALL); extra->border_trans = box->border_width / 2.0; element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); if (radius > 0.0) { /* Fix the handles, too */ elem->resize_handles[0].pos.x += radius; elem->resize_handles[0].pos.y += radius; elem->resize_handles[2].pos.x -= radius; elem->resize_handles[2].pos.y += radius; elem->resize_handles[5].pos.x += radius; elem->resize_handles[5].pos.y -= radius; elem->resize_handles[7].pos.x -= radius; elem->resize_handles[7].pos.y -= radius; } }
static void ellipse_update_data(Ellipse *ellipse, AnchorShape horiz, AnchorShape vert) { Element *elem = &ellipse->element; ElementBBExtras *extra = &elem->extra_spacing; DiaObject *obj = &elem->object; Point center, bottom_right; Point p, c; real dw, dh; real width, height; real radius1, radius2; int i; /* save starting points */ center = bottom_right = elem->corner; center.x += elem->width/2; bottom_right.x += elem->width; center.y += elem->height/2; bottom_right.y += elem->height; text_calc_boundingbox(ellipse->text, NULL); width = ellipse->text->max_width + 2 * ellipse->padding; height = ellipse->text->height * ellipse->text->numlines + 2 * ellipse->padding; /* stop ellipse from getting infinite width/height */ if (elem->width / elem->height > 4) elem->width = elem->height * 4; else if (elem->height / elem->width > 4) elem->height = elem->width * 4; c.x = elem->corner.x + elem->width / 2; c.y = elem->corner.y + elem->height / 2; p.x = c.x - width / 2; p.y = c.y - height / 2; radius1 = ellipse_radius(ellipse, p.x, p.y) - ellipse->border_width/2; radius2 = distance_point_point(&c, &p); if ( radius1 < radius2 && ( ellipse->text_fitting == TEXTFIT_ALWAYS || ellipse->text_fitting == TEXTFIT_WHEN_NEEDED)) { /* increase size of the ellipse while keeping its aspect ratio */ elem->width *= radius2 / radius1; elem->height *= radius2 / radius1; } /* move shape if necessary ... */ switch (horiz) { case ANCHOR_MIDDLE: elem->corner.x = center.x - elem->width/2; break; case ANCHOR_END: elem->corner.x = bottom_right.x - elem->width; break; default: break; } switch (vert) { case ANCHOR_MIDDLE: elem->corner.y = center.y - elem->height/2; break; case ANCHOR_END: elem->corner.y = bottom_right.y - elem->height; break; default: break; } p = elem->corner; p.x += elem->width / 2.0; p.y += elem->height / 2.0 - ellipse->text->height*ellipse->text->numlines/2 + ellipse->text->ascent; switch (ellipse->text->alignment) { case ALIGN_LEFT: p.x -= (elem->width - 2*(ellipse->padding + ellipse->border_width))/2; break; case ALIGN_RIGHT: p.x += (elem->width - 2*(ellipse->padding + ellipse->border_width))/2; break; case ALIGN_CENTER: break; } text_set_position(ellipse->text, &p); /* Update connections: */ c.x = elem->corner.x + elem->width / 2; c.y = elem->corner.y + elem->height / 2; dw = elem->width / 2.0; dh = elem->height / 2.0; for (i = 0; i < NUM_CONNECTIONS-1; i++) { real theta = M_PI / 8.0 * i; real costheta = cos(theta); real sintheta = sin(theta); connpoint_update(&ellipse->connections[i], c.x + dw * costheta, c.y - dh * sintheta, (costheta > .5?DIR_EAST:(costheta < -.5?DIR_WEST:0))| (sintheta > .5?DIR_NORTH:(sintheta < -.5?DIR_SOUTH:0))); } connpoint_update(&ellipse->connections[16], c.x, c.y, DIR_ALL); extra->border_trans = ellipse->border_width / 2.0; element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); }
static void attribute_update_data(Attribute *attribute) { Element *elem = &attribute->element; DiaObject *obj = &elem->object; Point center; ElementBBExtras *extra = &elem->extra_spacing; real half_x, half_y; attribute->name_width = dia_font_string_width(attribute->name, attribute->font, attribute->font_height); elem->width = attribute->name_width + 2*TEXT_BORDER_WIDTH_X; elem->height = attribute->font_height + 2*TEXT_BORDER_WIDTH_Y; center.x = elem->corner.x + elem->width / 2.0; center.y = elem->corner.y + elem->height / 2.0; half_x = elem->width * M_SQRT1_2 / 2.0; half_y = elem->height * M_SQRT1_2 / 2.0; /* Update connections: */ connpoint_update(&attribute->connections[0], center.x - half_x, center.y - half_y, DIR_NORTHWEST); connpoint_update(&attribute->connections[1], center.x, elem->corner.y, DIR_NORTH); connpoint_update(&attribute->connections[2], center.x + half_x, center.y - half_y, DIR_NORTHEAST); connpoint_update(&attribute->connections[3], elem->corner.x, center.y, DIR_WEST); connpoint_update(&attribute->connections[4], elem->corner.x + elem->width, elem->corner.y + elem->height / 2.0, DIR_EAST); connpoint_update(&attribute->connections[5], center.x - half_x, center.y + half_y, DIR_SOUTHWEST); connpoint_update(&attribute->connections[6], elem->corner.x + elem->width / 2.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&attribute->connections[7], center.x + half_x, center.y + half_y, DIR_SOUTHEAST); connpoint_update(&attribute->connections[8], center.x, center.y, DIR_ALL); extra->border_trans = attribute->border_width/2.0; element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); }
static void pgram_update_data(Pgram *pgram, AnchorShape horiz, AnchorShape vert) { Element *elem = &pgram->element; ElementBBExtras *extra = &elem->extra_spacing; DiaObject *obj = &elem->object; Point center, bottom_right; Point p; real offs; real width, height; real avail_width; real top_left; /* save starting points */ center = bottom_right = elem->corner; center.x += elem->width/2; bottom_right.x += elem->width; center.y += elem->height/2; bottom_right.y += elem->height; /* this takes the shearing of the parallelogram into account, so the * text can be extend to the edges of the parallelogram */ text_calc_boundingbox(pgram->text, NULL); height = pgram->text->height * pgram->text->numlines + pgram->padding*2 + pgram->border_width; if ( pgram->text_fitting == TEXTFIT_ALWAYS || (pgram->text_fitting == TEXTFIT_WHEN_NEEDED && height > elem->height)) elem->height = height; avail_width = elem->width - (pgram->padding*2 + pgram->border_width + fabs(pgram->shear_grad) * (elem->height + pgram->text->height * pgram->text->numlines)); if ( pgram->text_fitting == TEXTFIT_ALWAYS || (pgram->text_fitting == TEXTFIT_WHEN_NEEDED && avail_width < pgram->text->max_width)) { elem->width = (elem->width-avail_width) + pgram->text->max_width; avail_width = pgram->text->max_width; } /* width = pgram->text->max_width + pgram->padding*2 + pgram->border_width + fabs(pgram->shear_grad) * (elem->height + pgram->text->height * pgram->text->numlines); if (width > elem->width) elem->width = width; */ /* move shape if necessary ... */ switch (horiz) { case ANCHOR_MIDDLE: elem->corner.x = center.x - elem->width/2; break; case ANCHOR_END: elem->corner.x = bottom_right.x - elem->width; break; default: break; } switch (vert) { case ANCHOR_MIDDLE: elem->corner.y = center.y - elem->height/2; break; case ANCHOR_END: elem->corner.y = bottom_right.y - elem->height; break; default: break; } p = elem->corner; p.x += elem->width / 2.0; p.y += elem->height / 2.0 - pgram->text->height * pgram->text->numlines / 2 + pgram->text->ascent; switch (pgram->text->alignment) { case ALIGN_LEFT: p.x -= avail_width/2; break; case ALIGN_RIGHT: p.x += avail_width/2; break; case ALIGN_CENTER: break; } text_set_position(pgram->text, &p); /* 1/4 of how much more to the left the bottom line is */ offs = -(elem->height / 4.0 * pgram->shear_grad); width = elem->width - 4.0*fabs(offs); top_left = elem->corner.x; if (offs < 0.0) { top_left -= 4*offs; } /* Update connections: */ connpoint_update(&pgram->connections[0], top_left, elem->corner.y, DIR_NORTHWEST); connpoint_update(&pgram->connections[1], top_left + width / 4.0, elem->corner.y, DIR_NORTH); connpoint_update(&pgram->connections[2], top_left + width / 2.0, elem->corner.y, DIR_NORTH); connpoint_update(&pgram->connections[3], top_left + width * 3.0 / 4.0, elem->corner.y, DIR_NORTH); connpoint_update(&pgram->connections[4], top_left + width, elem->corner.y, DIR_NORTHEAST); connpoint_update(&pgram->connections[5], top_left + offs, elem->corner.y + elem->height / 4.0, DIR_WEST); connpoint_update(&pgram->connections[6], top_left + width + offs, elem->corner.y + elem->height / 4.0, DIR_EAST); connpoint_update(&pgram->connections[7], top_left + 2.0 * offs, elem->corner.y + elem->height / 2.0, DIR_WEST); connpoint_update(&pgram->connections[8], top_left + width + 2.0 * offs, elem->corner.y + elem->height / 2.0, DIR_EAST); connpoint_update(&pgram->connections[9], top_left + 3.0 * offs, elem->corner.y + elem->height * 3.0 / 4.0, DIR_WEST); connpoint_update(&pgram->connections[10], top_left + width + 3.0 * offs, elem->corner.y + elem->height * 3.0 / 4.0, DIR_EAST); connpoint_update(&pgram->connections[11], top_left + 4.0 * offs, elem->corner.y + elem->height, DIR_SOUTHWEST); connpoint_update(&pgram->connections[12], top_left + 4.0 * offs + width / 4.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&pgram->connections[13], top_left + 4.0 * offs + width / 2.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&pgram->connections[14], top_left + 4.0 * offs + 3.0 * width / 4.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&pgram->connections[15], top_left + 4.0 * offs + width, elem->corner.y + elem->height, DIR_SOUTHEAST); connpoint_update(&pgram->connections[16], top_left + 2.0 * offs + width / 2, elem->corner.y + elem->height / 2, DIR_ALL); extra->border_trans = pgram->border_width/2.0; element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); }
static void function_update_data(Function *pkg) { Element *elem = &pkg->element; DiaObject *obj = &elem->object; DiaFont *font; Point p1; real h, w = 0, font_height; text_calc_boundingbox(pkg->text, NULL) ; font = pkg->text->font ; font_height = pkg->text->height ; h = elem->corner.y + font_height/FUNCTION_MARGIN_Y; if (pkg->is_user) { h += 2*font_height/FUNCTION_MARGIN_SCALE; } w = MAX(w, pkg->text->max_width); p1.y = h + pkg->text->ascent - ( pkg->is_user ? font_height/FUNCTION_MARGIN_SCALE : 0 ); /* position of text */ h += pkg->text->height*pkg->text->numlines; h += font_height/FUNCTION_MARGIN_Y; w += 2*font_height/FUNCTION_MARGIN_X; p1.x = elem->corner.x + w/2.0 + ( pkg->is_user ? font_height/FUNCTION_MARGIN_SCALE : 0 ); text_set_position(pkg->text, &p1); if (pkg->is_user) { w += 2*font_height/FUNCTION_MARGIN_SCALE; } elem->width = w; elem->height = h - elem->corner.y; /* Update connections: */ connpoint_update(&pkg->connections[0], elem->corner.x, elem->corner.y, DIR_NORTHWEST); connpoint_update(&pkg->connections[1], elem->corner.x + elem->width / 2.0, elem->corner.y, DIR_NORTH); connpoint_update(&pkg->connections[2], elem->corner.x + elem->width, elem->corner.y, DIR_NORTHEAST); connpoint_update(&pkg->connections[3], elem->corner.x, elem->corner.y + elem->height / 2.0, DIR_WEST); connpoint_update(&pkg->connections[4], elem->corner.x + elem->width, elem->corner.y + elem->height / 2.0, DIR_EAST); connpoint_update(&pkg->connections[5], elem->corner.x, elem->corner.y + elem->height, DIR_SOUTHWEST); connpoint_update(&pkg->connections[6], elem->corner.x + elem->width / 2.0, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&pkg->connections[7], elem->corner.x + elem->width, elem->corner.y + elem->height, DIR_SOUTHEAST); connpoint_update(&pkg->connections[8], elem->corner.x + elem->width / 2.0, elem->corner.y + elem->height / 2.0, DIR_SOUTHEAST); element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); }
static void component_update_data(Component *cmp) { Element *elem = &cmp->element; DiaObject *obj = &elem->object; Point p; real cw2, ch; cmp->stereotype = remove_stereotype_from_string(cmp->stereotype); if (!cmp->st_stereotype) { cmp->st_stereotype = string_to_stereotype(cmp->stereotype); } text_calc_boundingbox(cmp->text, NULL); elem->width = cmp->text->max_width + 2*COMPONENT_MARGIN_X + COMPONENT_CWIDTH; elem->width = MAX(elem->width, 2*COMPONENT_CWIDTH); elem->height = cmp->text->height*cmp->text->numlines + cmp->text->descent + 0.1 + 2*COMPONENT_MARGIN_Y ; elem->height = MAX(elem->height, 5*COMPONENT_CHEIGHT); p = elem->corner; p.x += COMPONENT_CWIDTH + COMPONENT_MARGIN_X; p.y += COMPONENT_CHEIGHT; p.y += cmp->text->ascent; if (cmp->stereotype && cmp->stereotype[0] != '\0') { p.y += cmp->text->height; } text_set_position(cmp->text, &p); if (cmp->st_stereotype && cmp->st_stereotype[0] != '\0') { DiaFont *font; font = cmp->text->font; elem->height += cmp->text->height; elem->width = MAX(elem->width, dia_font_string_width(cmp->st_stereotype, font, cmp->text->height) + 2*COMPONENT_MARGIN_X + COMPONENT_CWIDTH); } cw2 = COMPONENT_CWIDTH/2; ch = COMPONENT_CHEIGHT; /* Update connections: */ connpoint_update(&cmp->connections[0], elem->corner.x + cw2, elem->corner.y, DIR_NORTH|DIR_WEST); connpoint_update(&cmp->connections[1], elem->corner.x + cw2 + (elem->width - cw2) / 2, elem->corner.y, DIR_NORTH); connpoint_update(&cmp->connections[2], elem->corner.x + elem->width, elem->corner.y, DIR_NORTH|DIR_EAST); connpoint_update(&cmp->connections[3], elem->corner.x + cw2, elem->corner.y + elem->height / 2.0, DIR_WEST); connpoint_update(&cmp->connections[4], elem->corner.x + elem->width, elem->corner.y + elem->height / 2.0, DIR_EAST); connpoint_update(&cmp->connections[5], elem->corner.x + cw2, elem->corner.y + elem->height, DIR_SOUTH|DIR_WEST); connpoint_update(&cmp->connections[6], elem->corner.x + cw2 + (elem->width - cw2)/2, elem->corner.y + elem->height, DIR_SOUTH); connpoint_update(&cmp->connections[7], elem->corner.x + elem->width, elem->corner.y + elem->height, DIR_SOUTH|DIR_EAST); connpoint_update(&cmp->connections[8], elem->corner.x, elem->corner.y + elem->height / 2.0 - ch, DIR_WEST); connpoint_update(&cmp->connections[9], elem->corner.x, elem->corner.y + elem->height / 2.0 + ch, DIR_WEST); connpoint_update(&cmp->connections[10], elem->corner.x + (elem->width-cw2)/2, elem->corner.y + elem->height / 2.0 + ch, DIR_ALL); element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); }
static void actor_update_data(Actor *actor, AnchorShape horiz, AnchorShape vert) { Element *elem = &actor->element; DiaObject *obj = &elem->object; ElementBBExtras *extra = &elem->extra_spacing; Point center, bottom_right,p,c; real width, height, dw, dh; real radius, mradius; int i; center = bottom_right = elem->corner; center.x += elem->width/2; bottom_right.x += elem->width; center.y += elem->height/2; bottom_right.y += elem->height; text_calc_boundingbox(actor->text, NULL); width = actor->text->max_width+0.5; height = actor->text->height * (actor->text->numlines + 3); /* added 3 blank lines for top */ /* minimal radius */ mradius=width; if (mradius<height) mradius=height; if (mradius<ACTOR_RADIUS) mradius=ACTOR_RADIUS; /* radius */ radius=elem->width; if (radius<elem->height) radius=elem->height; /* enforce (minimal or resized) radius */ if (radius<mradius) radius=mradius; elem->width=elem->height=radius; /* move shape if necessary ... (untouched) */ switch (horiz) { case ANCHOR_MIDDLE: elem->corner.x = center.x - elem->width/2; break; case ANCHOR_END: elem->corner.x = bottom_right.x - elem->width; break; default: break; } switch (vert) { case ANCHOR_MIDDLE: elem->corner.y = center.y - elem->height/2; break; case ANCHOR_END: elem->corner.y = bottom_right.y - elem->height; break; default: break; } p = elem->corner; p.x += elem->width / 2.0; p.y += elem->height / 2.0 - actor->text->height*actor->text->numlines/2 + actor->text->ascent; text_set_position(actor->text, &p); /* compute connection positions */ c.x = elem->corner.x + elem->width / 2; c.y = elem->corner.y + elem->height / 2; dw = elem->width / 2.0; dh = elem->height / 2.0; for (i = 0; i < NUM_CONNECTIONS-1; i++) { real theta = M_PI / 8.0 * i; real costheta = cos(theta); real sintheta = sin(theta); connpoint_update(&actor->connections[i], c.x + dw * costheta, c.y - dh * sintheta, (costheta > .5?DIR_EAST:(costheta < -.5?DIR_WEST:0))| (sintheta > .5?DIR_NORTH:(sintheta < -.5?DIR_SOUTH:0))); } actor->connections[16].pos.x = c.x; actor->connections[16].pos.y = c.y; extra->border_trans = ACTOR_BORDER_WIDTH / 2.0; element_update_boundingbox(elem); obj->position = elem->corner; element_update_handles(elem); }