mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-11 21:27:01 -04:00
Change tabs to two spaces.
This commit is contained in:
+88
-88
@@ -17,108 +17,108 @@ IMPLEMENT_VALUE_VIEWER(Choice);
|
||||
void get_options(Rotation& rot, ValueViewer& viewer, const ChoiceStyle& style, GeneratedImage::Options& opts);
|
||||
|
||||
bool ChoiceValueViewer::prepare(RotatedDC& dc) {
|
||||
return prepare_choice_viewer(dc, *this, style(), value().value());
|
||||
return prepare_choice_viewer(dc, *this, style(), value().value());
|
||||
}
|
||||
void ChoiceValueViewer::draw(RotatedDC& dc) {
|
||||
drawFieldBorder(dc);
|
||||
if (style().render_style & RENDER_HIDDEN) return;
|
||||
draw_choice_viewer(dc, *this, style(), value().value());
|
||||
drawFieldBorder(dc);
|
||||
if (style().render_style & RENDER_HIDDEN) return;
|
||||
draw_choice_viewer(dc, *this, style(), value().value());
|
||||
}
|
||||
|
||||
void ChoiceValueViewer::onStyleChange(int changes) {
|
||||
if (changes & CHANGE_MASK) style().image.clearCache();
|
||||
ValueViewer::onStyleChange(changes);
|
||||
if (changes & CHANGE_MASK) style().image.clearCache();
|
||||
ValueViewer::onStyleChange(changes);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Generic draw/prepare
|
||||
|
||||
bool prepare_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style, const String& value) {
|
||||
if (style.render_style & RENDER_IMAGE) {
|
||||
style.initImage();
|
||||
CachedScriptableImage& img = style.image;
|
||||
Context& ctx = viewer.viewer.getContext();
|
||||
ctx.setVariable(SCRIPT_VAR_input, to_script(value));
|
||||
// generate to determine the size
|
||||
if (img.update(ctx) && img.isReady()) {
|
||||
GeneratedImage::Options img_options;
|
||||
get_options(dc, viewer, style, img_options);
|
||||
// Generate image/bitmap (whichever is available)
|
||||
// don't worry, we cache the image
|
||||
ImageCombine combine = style.combine;
|
||||
Bitmap bitmap; Image image;
|
||||
RealSize size;
|
||||
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
||||
// store content properties
|
||||
if (style.content_width != size.width || style.content_height != size.height) {
|
||||
style.content_width = size.width;
|
||||
style.content_height = size.height;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (style.render_style & RENDER_IMAGE) {
|
||||
style.initImage();
|
||||
CachedScriptableImage& img = style.image;
|
||||
Context& ctx = viewer.viewer.getContext();
|
||||
ctx.setVariable(SCRIPT_VAR_input, to_script(value));
|
||||
// generate to determine the size
|
||||
if (img.update(ctx) && img.isReady()) {
|
||||
GeneratedImage::Options img_options;
|
||||
get_options(dc, viewer, style, img_options);
|
||||
// Generate image/bitmap (whichever is available)
|
||||
// don't worry, we cache the image
|
||||
ImageCombine combine = style.combine;
|
||||
Bitmap bitmap; Image image;
|
||||
RealSize size;
|
||||
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
||||
// store content properties
|
||||
if (style.content_width != size.width || style.content_height != size.height) {
|
||||
style.content_width = size.width;
|
||||
style.content_height = size.height;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void draw_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style, const String& value) {
|
||||
if (value.empty()) return;
|
||||
double margin = 0;
|
||||
if (style.render_style & RENDER_IMAGE) {
|
||||
// draw image
|
||||
CachedScriptableImage& img = style.image;
|
||||
if (style.content_dependent) {
|
||||
// re run script
|
||||
Context& ctx = viewer.viewer.getContext();
|
||||
ctx.setVariable(SCRIPT_VAR_input, to_script(value));
|
||||
img.update(ctx);
|
||||
}
|
||||
if (img.isReady()) {
|
||||
GeneratedImage::Options img_options;
|
||||
get_options(dc, viewer, style, img_options);
|
||||
// Generate image/bitmap
|
||||
ImageCombine combine = style.combine;
|
||||
Bitmap bitmap; Image image;
|
||||
RealSize size;
|
||||
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
||||
size = dc.trInvS(size);
|
||||
RealRect rect(align_in_rect(style.alignment, size, dc.getInternalRect()), size);
|
||||
if (bitmap.Ok()) {
|
||||
// just draw it
|
||||
dc.DrawPreRotatedBitmap(bitmap,rect);
|
||||
} else {
|
||||
// use combine mode
|
||||
dc.DrawPreRotatedImage(image,rect,combine);
|
||||
}
|
||||
margin = size.width + 2;
|
||||
} else if (viewer.nativeLook()) {
|
||||
// always have the margin
|
||||
margin = 18;
|
||||
}
|
||||
}
|
||||
if (style.render_style & RENDER_TEXT) {
|
||||
String text = tr(viewer.getStylePackage(), value, capitalize_sentence);
|
||||
Alignment text_align = style.alignment;
|
||||
if (style.render_style & RENDER_IMAGE) {
|
||||
text_align = ALIGN_MIDDLE_LEFT; // can't align both text and image in the same way
|
||||
}
|
||||
dc.SetFont(style.font, 1.0);
|
||||
RealSize size = dc.GetTextExtent(text);
|
||||
RealPoint pos = align_in_rect(text_align, size, dc.getInternalRect()) + RealSize(margin, 0);
|
||||
dc.DrawTextWithShadow(text, style.font, pos);
|
||||
}
|
||||
if (value.empty()) return;
|
||||
double margin = 0;
|
||||
if (style.render_style & RENDER_IMAGE) {
|
||||
// draw image
|
||||
CachedScriptableImage& img = style.image;
|
||||
if (style.content_dependent) {
|
||||
// re run script
|
||||
Context& ctx = viewer.viewer.getContext();
|
||||
ctx.setVariable(SCRIPT_VAR_input, to_script(value));
|
||||
img.update(ctx);
|
||||
}
|
||||
if (img.isReady()) {
|
||||
GeneratedImage::Options img_options;
|
||||
get_options(dc, viewer, style, img_options);
|
||||
// Generate image/bitmap
|
||||
ImageCombine combine = style.combine;
|
||||
Bitmap bitmap; Image image;
|
||||
RealSize size;
|
||||
img.generateCached(img_options, &style.mask, &combine, &bitmap, &image, &size);
|
||||
size = dc.trInvS(size);
|
||||
RealRect rect(align_in_rect(style.alignment, size, dc.getInternalRect()), size);
|
||||
if (bitmap.Ok()) {
|
||||
// just draw it
|
||||
dc.DrawPreRotatedBitmap(bitmap,rect);
|
||||
} else {
|
||||
// use combine mode
|
||||
dc.DrawPreRotatedImage(image,rect,combine);
|
||||
}
|
||||
margin = size.width + 2;
|
||||
} else if (viewer.nativeLook()) {
|
||||
// always have the margin
|
||||
margin = 18;
|
||||
}
|
||||
}
|
||||
if (style.render_style & RENDER_TEXT) {
|
||||
String text = tr(viewer.getStylePackage(), value, capitalize_sentence);
|
||||
Alignment text_align = style.alignment;
|
||||
if (style.render_style & RENDER_IMAGE) {
|
||||
text_align = ALIGN_MIDDLE_LEFT; // can't align both text and image in the same way
|
||||
}
|
||||
dc.SetFont(style.font, 1.0);
|
||||
RealSize size = dc.GetTextExtent(text);
|
||||
RealPoint pos = align_in_rect(text_align, size, dc.getInternalRect()) + RealSize(margin, 0);
|
||||
dc.DrawTextWithShadow(text, style.font, pos);
|
||||
}
|
||||
}
|
||||
|
||||
void get_options(Rotation& rot, ValueViewer& viewer, const ChoiceStyle& style, GeneratedImage::Options& opts) {
|
||||
opts.package = &viewer.getStylePackage();
|
||||
opts.local_package = &viewer.getLocalPackage();
|
||||
opts.angle = rot.getAngle();
|
||||
if (viewer.nativeLook()) {
|
||||
opts.width = opts.height = 16;
|
||||
opts.preserve_aspect = ASPECT_BORDER;
|
||||
} else if(style.render_style & RENDER_TEXT) {
|
||||
// also drawing text, use original size
|
||||
} else {
|
||||
opts.width = (int) rot.trX(style.width);
|
||||
opts.height = (int) rot.trY(style.height);
|
||||
opts.preserve_aspect = (style.alignment & ALIGN_STRETCH) ? ASPECT_STRETCH : ASPECT_FIT;
|
||||
}
|
||||
opts.package = &viewer.getStylePackage();
|
||||
opts.local_package = &viewer.getLocalPackage();
|
||||
opts.angle = rot.getAngle();
|
||||
if (viewer.nativeLook()) {
|
||||
opts.width = opts.height = 16;
|
||||
opts.preserve_aspect = ASPECT_BORDER;
|
||||
} else if(style.render_style & RENDER_TEXT) {
|
||||
// also drawing text, use original size
|
||||
} else {
|
||||
opts.width = (int) rot.trX(style.width);
|
||||
opts.height = (int) rot.trY(style.height);
|
||||
opts.preserve_aspect = (style.alignment & ALIGN_STRETCH) ? ASPECT_STRETCH : ASPECT_FIT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
/// Viewer that displays a choice value
|
||||
class ChoiceValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(Choice) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual bool prepare(RotatedDC& dc);
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onStyleChange(int);
|
||||
DECLARE_VALUE_VIEWER(Choice) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual bool prepare(RotatedDC& dc);
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onStyleChange(int);
|
||||
};
|
||||
|
||||
bool prepare_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style, const String& value);
|
||||
|
||||
+62
-62
@@ -17,69 +17,69 @@ DECLARE_TYPEOF_COLLECTION(ColorField::ChoiceP);
|
||||
IMPLEMENT_VALUE_VIEWER(Color);
|
||||
|
||||
void ColorValueViewer::draw(RotatedDC& dc) {
|
||||
// draw in the value color
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(value().value());
|
||||
if (nativeLook()) {
|
||||
// native look
|
||||
// find name of color
|
||||
String color_name = _("Custom");
|
||||
if (field().default_script && value().value.isDefault()) {
|
||||
color_name = field().default_name;
|
||||
} else {
|
||||
FOR_EACH_CONST(c, field().choices) {
|
||||
if (value().value() == c->color) {
|
||||
color_name = capitalize(c->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// draw name and color
|
||||
dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
||||
dc.DrawRectangle(RealRect(0, 0, 40, dc.getHeight()));
|
||||
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.DrawRectangle(RealRect(40, 0, dc.getWidth()-40, dc.getHeight()));
|
||||
dc.DrawText(color_name, RealPoint(43, 3));
|
||||
} else {
|
||||
// is there a mask?
|
||||
const AlphaMask& alpha_mask = getMask(dc);
|
||||
if (alpha_mask.isLoaded()) {
|
||||
dc.DrawImage(alpha_mask.colorImage(value().value()), RealPoint(0,0), style().combine);
|
||||
} else {
|
||||
// do we need clipping?
|
||||
bool clip = style().left_width < style().width && style().right_width < style().width &&
|
||||
style().top_width < style().height && style().bottom_width < style().height;
|
||||
if (clip) {
|
||||
// clip away the inside of the rectangle
|
||||
wxRegion r = dc.trRectToRegion(style().getInternalRect());
|
||||
r.Subtract(dc.trRectToRegion(RealRect(
|
||||
style().left_width,
|
||||
style().top_width,
|
||||
style().width - style().left_width - style().right_width,
|
||||
style().height - style().top_width - style().bottom_width
|
||||
)));
|
||||
dc.getDC().SetClippingRegion(r);
|
||||
}
|
||||
dc.DrawRoundedRectangle(style().getInternalRect(), style().radius);
|
||||
if (clip) dc.getDC().DestroyClippingRegion();
|
||||
}
|
||||
drawFieldBorder(dc);
|
||||
}
|
||||
// draw in the value color
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(value().value());
|
||||
if (nativeLook()) {
|
||||
// native look
|
||||
// find name of color
|
||||
String color_name = _("Custom");
|
||||
if (field().default_script && value().value.isDefault()) {
|
||||
color_name = field().default_name;
|
||||
} else {
|
||||
FOR_EACH_CONST(c, field().choices) {
|
||||
if (value().value() == c->color) {
|
||||
color_name = capitalize(c->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// draw name and color
|
||||
dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
||||
dc.DrawRectangle(RealRect(0, 0, 40, dc.getHeight()));
|
||||
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.DrawRectangle(RealRect(40, 0, dc.getWidth()-40, dc.getHeight()));
|
||||
dc.DrawText(color_name, RealPoint(43, 3));
|
||||
} else {
|
||||
// is there a mask?
|
||||
const AlphaMask& alpha_mask = getMask(dc);
|
||||
if (alpha_mask.isLoaded()) {
|
||||
dc.DrawImage(alpha_mask.colorImage(value().value()), RealPoint(0,0), style().combine);
|
||||
} else {
|
||||
// do we need clipping?
|
||||
bool clip = style().left_width < style().width && style().right_width < style().width &&
|
||||
style().top_width < style().height && style().bottom_width < style().height;
|
||||
if (clip) {
|
||||
// clip away the inside of the rectangle
|
||||
wxRegion r = dc.trRectToRegion(style().getInternalRect());
|
||||
r.Subtract(dc.trRectToRegion(RealRect(
|
||||
style().left_width,
|
||||
style().top_width,
|
||||
style().width - style().left_width - style().right_width,
|
||||
style().height - style().top_width - style().bottom_width
|
||||
)));
|
||||
dc.getDC().SetClippingRegion(r);
|
||||
}
|
||||
dc.DrawRoundedRectangle(style().getInternalRect(), style().radius);
|
||||
if (clip) dc.getDC().DestroyClippingRegion();
|
||||
}
|
||||
drawFieldBorder(dc);
|
||||
}
|
||||
}
|
||||
|
||||
bool ColorValueViewer::containsPoint(const RealPoint& p) const {
|
||||
// check against mask
|
||||
const AlphaMask& alpha_mask = getMask();
|
||||
if (alpha_mask.isLoaded()) {
|
||||
// check against mask
|
||||
return alpha_mask.isOpaque(p, style().getSize());
|
||||
} else {
|
||||
double left = p.x, right = style().width - p.x - 1;
|
||||
double top = p.y, bottom = style().height - p.y - 1;
|
||||
if (left < 0 || right < 0 || top < 0 || bottom < 0) return false; // outside bounding box
|
||||
// check against border
|
||||
return left < style().left_width || right < style().right_width // inside horizontal border
|
||||
|| top < style().top_width || bottom < style().bottom_width; // inside vertical border
|
||||
}
|
||||
// check against mask
|
||||
const AlphaMask& alpha_mask = getMask();
|
||||
if (alpha_mask.isLoaded()) {
|
||||
// check against mask
|
||||
return alpha_mask.isOpaque(p, style().getSize());
|
||||
} else {
|
||||
double left = p.x, right = style().width - p.x - 1;
|
||||
double top = p.y, bottom = style().height - p.y - 1;
|
||||
if (left < 0 || right < 0 || top < 0 || bottom < 0) return false; // outside bounding box
|
||||
// check against border
|
||||
return left < style().left_width || right < style().right_width // inside horizontal border
|
||||
|| top < style().top_width || bottom < style().bottom_width; // inside vertical border
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ DECLARE_POINTER_TYPE(AlphaMask);
|
||||
/// Viewer that displays a color value
|
||||
class ColorValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(Color) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual bool containsPoint(const RealPoint& p) const;
|
||||
DECLARE_VALUE_VIEWER(Color) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual bool containsPoint(const RealPoint& p) const;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
+105
-105
@@ -16,122 +16,122 @@
|
||||
IMPLEMENT_VALUE_VIEWER(Image);
|
||||
|
||||
void ImageValueViewer::draw(RotatedDC& dc) {
|
||||
DrawWhat what = viewer.drawWhat(this);
|
||||
// reset?
|
||||
int w = max(0,(int)dc.trX(style().width)), h = max(0,(int)dc.trY(style().height));
|
||||
Radians a = dc.getAngle();
|
||||
const AlphaMask& alpha_mask = getMask(w,h);
|
||||
if (bitmap.Ok() && (a != angle || size.width != w || size.height != h)) {
|
||||
bitmap = Bitmap();
|
||||
}
|
||||
// try to load image
|
||||
if (!bitmap.Ok()) {
|
||||
angle = a;
|
||||
is_default = false;
|
||||
Image image;
|
||||
// load from file
|
||||
if (!value().filename.empty()) {
|
||||
try {
|
||||
InputStreamP image_file = getLocalPackage().openIn(value().filename);
|
||||
if (image.LoadFile(*image_file)) {
|
||||
image.Rescale(w, h);
|
||||
}
|
||||
} CATCH_ALL_ERRORS(false);
|
||||
}
|
||||
// nice placeholder
|
||||
if (!image.Ok() && style().default_image.isReady()) {
|
||||
image = style().default_image.generate(GeneratedImage::Options(w, h, &getStylePackage(), &getLocalPackage()));
|
||||
is_default = true;
|
||||
if (what & DRAW_EDITING) {
|
||||
bitmap = imagePlaceholder(dc, w, h, image, what & DRAW_EDITING);
|
||||
if (alpha_mask.isLoaded() || !is_rad0(a)) {
|
||||
image = bitmap.ConvertToImage(); // we need to convert back to an image
|
||||
} else {
|
||||
image = Image();
|
||||
}
|
||||
}
|
||||
}
|
||||
// checkerboard placeholder
|
||||
if (!image.Ok() && !bitmap.Ok() && style().width > 40) {
|
||||
// placeholder bitmap
|
||||
bitmap = imagePlaceholder(dc, w, h, wxNullImage, what & DRAW_EDITING);
|
||||
if (alpha_mask.isLoaded() || !is_rad0(a)) {
|
||||
// we need to convert back to an image
|
||||
image = bitmap.ConvertToImage();
|
||||
}
|
||||
}
|
||||
// done
|
||||
if (image.Ok()) {
|
||||
// apply mask and rotate
|
||||
alpha_mask.setAlpha(image);
|
||||
size = RealSize(image);
|
||||
image = rotate_image(image, angle);
|
||||
bitmap = Bitmap(image);
|
||||
}
|
||||
}
|
||||
// border
|
||||
drawFieldBorder(dc);
|
||||
// draw image, if any
|
||||
if (bitmap.Ok()) {
|
||||
dc.DrawPreRotatedBitmap(bitmap, dc.getInternalRect());
|
||||
}
|
||||
DrawWhat what = viewer.drawWhat(this);
|
||||
// reset?
|
||||
int w = max(0,(int)dc.trX(style().width)), h = max(0,(int)dc.trY(style().height));
|
||||
Radians a = dc.getAngle();
|
||||
const AlphaMask& alpha_mask = getMask(w,h);
|
||||
if (bitmap.Ok() && (a != angle || size.width != w || size.height != h)) {
|
||||
bitmap = Bitmap();
|
||||
}
|
||||
// try to load image
|
||||
if (!bitmap.Ok()) {
|
||||
angle = a;
|
||||
is_default = false;
|
||||
Image image;
|
||||
// load from file
|
||||
if (!value().filename.empty()) {
|
||||
try {
|
||||
InputStreamP image_file = getLocalPackage().openIn(value().filename);
|
||||
if (image.LoadFile(*image_file)) {
|
||||
image.Rescale(w, h);
|
||||
}
|
||||
} CATCH_ALL_ERRORS(false);
|
||||
}
|
||||
// nice placeholder
|
||||
if (!image.Ok() && style().default_image.isReady()) {
|
||||
image = style().default_image.generate(GeneratedImage::Options(w, h, &getStylePackage(), &getLocalPackage()));
|
||||
is_default = true;
|
||||
if (what & DRAW_EDITING) {
|
||||
bitmap = imagePlaceholder(dc, w, h, image, what & DRAW_EDITING);
|
||||
if (alpha_mask.isLoaded() || !is_rad0(a)) {
|
||||
image = bitmap.ConvertToImage(); // we need to convert back to an image
|
||||
} else {
|
||||
image = Image();
|
||||
}
|
||||
}
|
||||
}
|
||||
// checkerboard placeholder
|
||||
if (!image.Ok() && !bitmap.Ok() && style().width > 40) {
|
||||
// placeholder bitmap
|
||||
bitmap = imagePlaceholder(dc, w, h, wxNullImage, what & DRAW_EDITING);
|
||||
if (alpha_mask.isLoaded() || !is_rad0(a)) {
|
||||
// we need to convert back to an image
|
||||
image = bitmap.ConvertToImage();
|
||||
}
|
||||
}
|
||||
// done
|
||||
if (image.Ok()) {
|
||||
// apply mask and rotate
|
||||
alpha_mask.setAlpha(image);
|
||||
size = RealSize(image);
|
||||
image = rotate_image(image, angle);
|
||||
bitmap = Bitmap(image);
|
||||
}
|
||||
}
|
||||
// border
|
||||
drawFieldBorder(dc);
|
||||
// draw image, if any
|
||||
if (bitmap.Ok()) {
|
||||
dc.DrawPreRotatedBitmap(bitmap, dc.getInternalRect());
|
||||
}
|
||||
}
|
||||
|
||||
void ImageValueViewer::onValueChange() {
|
||||
bitmap = Bitmap();
|
||||
bitmap = Bitmap();
|
||||
}
|
||||
|
||||
void ImageValueViewer::onStyleChange(int changes) {
|
||||
if ((changes & CHANGE_MASK) ||
|
||||
((changes & CHANGE_DEFAULT) && is_default)) {
|
||||
bitmap = Bitmap();
|
||||
}
|
||||
ValueViewer::onStyleChange(changes);
|
||||
if ((changes & CHANGE_MASK) ||
|
||||
((changes & CHANGE_DEFAULT) && is_default)) {
|
||||
bitmap = Bitmap();
|
||||
}
|
||||
ValueViewer::onStyleChange(changes);
|
||||
}
|
||||
|
||||
// is an image very light?
|
||||
bool very_light(const Image& image) {
|
||||
int w = image.GetWidth(), h = image.GetHeight();
|
||||
if (w*h<1) return false;
|
||||
Byte* data = image.GetData();
|
||||
int middle = w / 2 + (h*w) / 2;
|
||||
int total = (int)data[3 * middle] + (int)data[3 * middle + 1] + (int)data[3 * middle + 2];
|
||||
return total >= 210 * 3;
|
||||
int w = image.GetWidth(), h = image.GetHeight();
|
||||
if (w*h<1) return false;
|
||||
Byte* data = image.GetData();
|
||||
int middle = w / 2 + (h*w) / 2;
|
||||
int total = (int)data[3 * middle] + (int)data[3 * middle + 1] + (int)data[3 * middle + 2];
|
||||
return total >= 210 * 3;
|
||||
}
|
||||
|
||||
Bitmap ImageValueViewer::imagePlaceholder(const Rotation& rot, UInt w, UInt h, const Image& background, bool editing) {
|
||||
// Bitmap and memory dc
|
||||
Bitmap bmp(w, h, 24);
|
||||
wxMemoryDC mdc;
|
||||
mdc.SelectObject(bmp);
|
||||
RealRect rect(0,0,w,h);
|
||||
RotatedDC dc(mdc, 0, rect, 1.0, QUALITY_AA);
|
||||
// Draw (checker) background
|
||||
if (!background.Ok() || background.HasAlpha()) {
|
||||
draw_checker(dc, rect);
|
||||
}
|
||||
if (background.Ok()) {
|
||||
dc.DrawImage(background, RealPoint(0,0));
|
||||
}
|
||||
// Draw text
|
||||
if (editing) {
|
||||
// only when in editor mode
|
||||
for (UInt size = 12 ; size > 2 ; --size) {
|
||||
dc.SetFont(wxFont(size, wxSWISS, wxNORMAL, wxNORMAL));
|
||||
RealSize rs = dc.GetTextExtent(_("double click to load image"));
|
||||
if (rs.width <= w - 10 && rs.height < h - 10) {
|
||||
// text fits
|
||||
RealPoint pos = align_in_rect(ALIGN_MIDDLE_CENTER, rs, rect);
|
||||
bool black_on_white = !background.Ok() || very_light(background);
|
||||
dc.SetTextForeground(black_on_white ? *wxWHITE : *wxBLACK);
|
||||
dc.DrawText(_("double click to load image"), pos, 2, 4); // blurred
|
||||
dc.SetTextForeground(black_on_white ? *wxBLACK : *wxWHITE);
|
||||
dc.DrawText(_("double click to load image"), pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Done
|
||||
mdc.SelectObject(wxNullBitmap);
|
||||
return bmp;
|
||||
// Bitmap and memory dc
|
||||
Bitmap bmp(w, h, 24);
|
||||
wxMemoryDC mdc;
|
||||
mdc.SelectObject(bmp);
|
||||
RealRect rect(0,0,w,h);
|
||||
RotatedDC dc(mdc, 0, rect, 1.0, QUALITY_AA);
|
||||
// Draw (checker) background
|
||||
if (!background.Ok() || background.HasAlpha()) {
|
||||
draw_checker(dc, rect);
|
||||
}
|
||||
if (background.Ok()) {
|
||||
dc.DrawImage(background, RealPoint(0,0));
|
||||
}
|
||||
// Draw text
|
||||
if (editing) {
|
||||
// only when in editor mode
|
||||
for (UInt size = 12 ; size > 2 ; --size) {
|
||||
dc.SetFont(wxFont(size, wxSWISS, wxNORMAL, wxNORMAL));
|
||||
RealSize rs = dc.GetTextExtent(_("double click to load image"));
|
||||
if (rs.width <= w - 10 && rs.height < h - 10) {
|
||||
// text fits
|
||||
RealPoint pos = align_in_rect(ALIGN_MIDDLE_CENTER, rs, rect);
|
||||
bool black_on_white = !background.Ok() || very_light(background);
|
||||
dc.SetTextForeground(black_on_white ? *wxWHITE : *wxBLACK);
|
||||
dc.DrawText(_("double click to load image"), pos, 2, 4); // blurred
|
||||
dc.SetTextForeground(black_on_white ? *wxBLACK : *wxWHITE);
|
||||
dc.DrawText(_("double click to load image"), pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Done
|
||||
mdc.SelectObject(wxNullBitmap);
|
||||
return bmp;
|
||||
}
|
||||
|
||||
+13
-13
@@ -20,20 +20,20 @@ DECLARE_POINTER_TYPE(AlphaMask);
|
||||
/// Viewer that displays an image value
|
||||
class ImageValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(Image) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onValueChange();
|
||||
virtual void onStyleChange(int);
|
||||
|
||||
DECLARE_VALUE_VIEWER(Image) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onValueChange();
|
||||
virtual void onStyleChange(int);
|
||||
|
||||
private:
|
||||
Bitmap bitmap; ///< Cached bitmap
|
||||
RealSize size; ///< Size of cached bitmap
|
||||
Radians angle; ///< Angle of cached bitmap
|
||||
bool is_default; ///< Is the default placeholder image used?
|
||||
|
||||
/// Generate a placeholder image
|
||||
static Bitmap imagePlaceholder(const Rotation& rot, UInt w, UInt h, const Image& background, bool editing);
|
||||
Bitmap bitmap; ///< Cached bitmap
|
||||
RealSize size; ///< Size of cached bitmap
|
||||
Radians angle; ///< Angle of cached bitmap
|
||||
bool is_default; ///< Is the default placeholder image used?
|
||||
|
||||
/// Generate a placeholder image
|
||||
static Bitmap imagePlaceholder(const Rotation& rot, UInt w, UInt h, const Image& background, bool editing);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -15,26 +15,26 @@
|
||||
IMPLEMENT_VALUE_VIEWER(Info);
|
||||
|
||||
void InfoValueViewer::draw(RotatedDC& dc) {
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
if (nativeLook()) {
|
||||
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
||||
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
|
||||
dc.SetFont(wxFont(16, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, _("Arial")));
|
||||
} else {
|
||||
dc.SetTextForeground(style().font.color);
|
||||
dc.SetBrush(style().background_color);
|
||||
dc.SetFont(style().font, 1.0);
|
||||
}
|
||||
// draw background
|
||||
RealRect rect = style().getInternalRect();
|
||||
dc.DrawRectangle(rect.grow(2));
|
||||
// draw text
|
||||
rect = rect.move(
|
||||
style().padding_left,
|
||||
style().padding_top,
|
||||
-style().padding_left - style().padding_right,
|
||||
-style().padding_top - style().padding_bottom
|
||||
);
|
||||
RealSize size = dc.GetTextExtent(value().value);
|
||||
dc.DrawText(value().value, align_in_rect(style().alignment, size, rect));
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
if (nativeLook()) {
|
||||
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
||||
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE));
|
||||
dc.SetFont(wxFont(16, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, _("Arial")));
|
||||
} else {
|
||||
dc.SetTextForeground(style().font.color);
|
||||
dc.SetBrush(style().background_color);
|
||||
dc.SetFont(style().font, 1.0);
|
||||
}
|
||||
// draw background
|
||||
RealRect rect = style().getInternalRect();
|
||||
dc.DrawRectangle(rect.grow(2));
|
||||
// draw text
|
||||
rect = rect.move(
|
||||
style().padding_left,
|
||||
style().padding_top,
|
||||
-style().padding_left - style().padding_right,
|
||||
-style().padding_top - style().padding_bottom
|
||||
);
|
||||
RealSize size = dc.GetTextExtent(value().value);
|
||||
dc.DrawText(value().value, align_in_rect(style().alignment, size, rect));
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
/// Viewer that displays a text value
|
||||
class InfoValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(Info) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
DECLARE_VALUE_VIEWER(Info) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -19,72 +19,72 @@ DECLARE_TYPEOF_COLLECTION(String);
|
||||
IMPLEMENT_VALUE_VIEWER(MultipleChoice);
|
||||
|
||||
bool MultipleChoiceValueViewer::prepare(RotatedDC& dc) {
|
||||
if (style().render_style & (RENDER_CHECKLIST | RENDER_LIST)) return false;
|
||||
return prepare_choice_viewer(dc, *this, style(), value().value());
|
||||
if (style().render_style & (RENDER_CHECKLIST | RENDER_LIST)) return false;
|
||||
return prepare_choice_viewer(dc, *this, style(), value().value());
|
||||
}
|
||||
|
||||
void MultipleChoiceValueViewer::draw(RotatedDC& dc) {
|
||||
drawFieldBorder(dc);
|
||||
if (style().render_style & RENDER_HIDDEN) return;
|
||||
RealPoint pos = align_in_rect(style().alignment, RealSize(0,0), style().getInternalRect());
|
||||
// selected choices
|
||||
vector<String> selected;
|
||||
value().get(selected);
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
// render all choices
|
||||
int end = field().choices->lastId();
|
||||
vector<String>::iterator select_it = selected.begin();
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String choice = field().choices->choiceName(i);
|
||||
bool active = select_it != selected.end() && *select_it == choice;
|
||||
if (active) select_it++;
|
||||
drawChoice(dc, pos, choice, active);
|
||||
}
|
||||
} else if (style().render_style & RENDER_LIST) {
|
||||
// render only selected choices
|
||||
FOR_EACH(choice, selected) {
|
||||
drawChoice(dc, pos, choice);
|
||||
}
|
||||
} else {
|
||||
draw_choice_viewer(dc, *this, style(), value().value());
|
||||
}
|
||||
drawFieldBorder(dc);
|
||||
if (style().render_style & RENDER_HIDDEN) return;
|
||||
RealPoint pos = align_in_rect(style().alignment, RealSize(0,0), style().getInternalRect());
|
||||
// selected choices
|
||||
vector<String> selected;
|
||||
value().get(selected);
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
// render all choices
|
||||
int end = field().choices->lastId();
|
||||
vector<String>::iterator select_it = selected.begin();
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String choice = field().choices->choiceName(i);
|
||||
bool active = select_it != selected.end() && *select_it == choice;
|
||||
if (active) select_it++;
|
||||
drawChoice(dc, pos, choice, active);
|
||||
}
|
||||
} else if (style().render_style & RENDER_LIST) {
|
||||
// render only selected choices
|
||||
FOR_EACH(choice, selected) {
|
||||
drawChoice(dc, pos, choice);
|
||||
}
|
||||
} else {
|
||||
draw_choice_viewer(dc, *this, style(), value().value());
|
||||
}
|
||||
}
|
||||
|
||||
void MultipleChoiceValueViewer::drawChoice(RotatedDC& dc, RealPoint& pos, const String& choice, bool active) {
|
||||
RealSize size; size.height = item_height;
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
wxRect rect = dc.trRectToBB(RealRect(pos + RealSize(1,1), RealSize(12,12)));
|
||||
draw_checkbox(nullptr, dc.getDC(), rect, active); // TODO
|
||||
size = add_horizontal(size, RealSize(14,16));
|
||||
}
|
||||
if (style().render_style & RENDER_IMAGE) {
|
||||
map<String,ScriptableImage>::iterator it = style().choice_images.find(canonical_name_form(choice));
|
||||
if (it != style().choice_images.end() && it->second.isReady()) {
|
||||
// TODO: caching
|
||||
GeneratedImage::Options options(0,0, &getStylePackage(), &getLocalPackage());
|
||||
options.zoom = dc.getZoom();
|
||||
options.angle = dc.getAngle();
|
||||
Image image = it->second.generate(options);
|
||||
ImageCombine combine = it->second.combine();
|
||||
// TODO : alignment?
|
||||
dc.DrawPreRotatedImage(image, RealRect(pos.x + size.width, pos.y, options.width, options.height), combine == COMBINE_DEFAULT ? style().combine : combine);
|
||||
size = add_horizontal(size, dc.trInvS(RealSize(options.width,options.height)));
|
||||
}
|
||||
}
|
||||
if (style().render_style & RENDER_TEXT) {
|
||||
// draw text
|
||||
String text = tr(getStylePackage(), choice, capitalize_sentence);
|
||||
dc.SetFont(style().font,1);
|
||||
RealSize text_size = dc.GetTextExtent(text);
|
||||
RealPoint text_pos = align_in_rect(ALIGN_MIDDLE_LEFT, text_size, RealRect(pos.x + size.width + 1, pos.y, 0,size.height));
|
||||
dc.DrawTextWithShadow(text, style().font, text_pos);
|
||||
size = add_horizontal(size, text_size);
|
||||
}
|
||||
// next position
|
||||
pos = move_in_direction(style().direction, pos, size, style().spacing);
|
||||
RealSize size; size.height = item_height;
|
||||
if (style().render_style & RENDER_CHECKLIST) {
|
||||
wxRect rect = dc.trRectToBB(RealRect(pos + RealSize(1,1), RealSize(12,12)));
|
||||
draw_checkbox(nullptr, dc.getDC(), rect, active); // TODO
|
||||
size = add_horizontal(size, RealSize(14,16));
|
||||
}
|
||||
if (style().render_style & RENDER_IMAGE) {
|
||||
map<String,ScriptableImage>::iterator it = style().choice_images.find(canonical_name_form(choice));
|
||||
if (it != style().choice_images.end() && it->second.isReady()) {
|
||||
// TODO: caching
|
||||
GeneratedImage::Options options(0,0, &getStylePackage(), &getLocalPackage());
|
||||
options.zoom = dc.getZoom();
|
||||
options.angle = dc.getAngle();
|
||||
Image image = it->second.generate(options);
|
||||
ImageCombine combine = it->second.combine();
|
||||
// TODO : alignment?
|
||||
dc.DrawPreRotatedImage(image, RealRect(pos.x + size.width, pos.y, options.width, options.height), combine == COMBINE_DEFAULT ? style().combine : combine);
|
||||
size = add_horizontal(size, dc.trInvS(RealSize(options.width,options.height)));
|
||||
}
|
||||
}
|
||||
if (style().render_style & RENDER_TEXT) {
|
||||
// draw text
|
||||
String text = tr(getStylePackage(), choice, capitalize_sentence);
|
||||
dc.SetFont(style().font,1);
|
||||
RealSize text_size = dc.GetTextExtent(text);
|
||||
RealPoint text_pos = align_in_rect(ALIGN_MIDDLE_LEFT, text_size, RealRect(pos.x + size.width + 1, pos.y, 0,size.height));
|
||||
dc.DrawTextWithShadow(text, style().font, text_pos);
|
||||
size = add_horizontal(size, text_size);
|
||||
}
|
||||
// next position
|
||||
pos = move_in_direction(style().direction, pos, size, style().spacing);
|
||||
}
|
||||
|
||||
void MultipleChoiceValueViewer::onStyleChange(int changes) {
|
||||
if (changes & CHANGE_MASK) style().image.clearCache();
|
||||
ValueViewer::onStyleChange(changes);
|
||||
if (changes & CHANGE_MASK) style().image.clearCache();
|
||||
ValueViewer::onStyleChange(changes);
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
/// Viewer that displays a multiple choice value
|
||||
class MultipleChoiceValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(MultipleChoice) : ValueViewer(parent,style), item_height(0) {}
|
||||
|
||||
virtual bool prepare(RotatedDC& dc);
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onStyleChange(int);
|
||||
DECLARE_VALUE_VIEWER(MultipleChoice) : ValueViewer(parent,style), item_height(0) {}
|
||||
|
||||
virtual bool prepare(RotatedDC& dc);
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onStyleChange(int);
|
||||
protected:
|
||||
double item_height; ///< Height of a single item, or 0 if non uniform
|
||||
double item_height; ///< Height of a single item, or 0 if non uniform
|
||||
private:
|
||||
void drawChoice(RotatedDC& dc, RealPoint& pos, const String& choice, bool active = true);
|
||||
void drawChoice(RotatedDC& dc, RealPoint& pos, const String& choice, bool active = true);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -18,53 +18,53 @@ DECLARE_TYPEOF_COLLECTION(PackageChoiceValueViewer::Item);
|
||||
IMPLEMENT_VALUE_VIEWER(PackageChoice);
|
||||
|
||||
struct PackageChoiceValueViewer::ComparePackagePosHint {
|
||||
bool operator () (const PackagedP& a, const PackagedP& b) {
|
||||
// use position_hints to determine order
|
||||
if (a->position_hint < b->position_hint) return true;
|
||||
if (a->position_hint > b->position_hint) return false;
|
||||
// ensure a deterministic order: use the names
|
||||
return a->name() < b->name();
|
||||
}
|
||||
bool operator () (const PackagedP& a, const PackagedP& b) {
|
||||
// use position_hints to determine order
|
||||
if (a->position_hint < b->position_hint) return true;
|
||||
if (a->position_hint > b->position_hint) return false;
|
||||
// ensure a deterministic order: use the names
|
||||
return a->name() < b->name();
|
||||
}
|
||||
};
|
||||
|
||||
void PackageChoiceValueViewer::initItems() {
|
||||
vector<PackagedP> choices;
|
||||
package_manager.findMatching(field().match, choices);
|
||||
sort(choices.begin(), choices.end(), ComparePackagePosHint());
|
||||
FOR_EACH(p, choices) {
|
||||
Item i;
|
||||
i.package_name = p->relativeFilename();
|
||||
i.name = capitalize_sentence(p->short_name);
|
||||
Image image;
|
||||
InputStreamP stream = p->openIconFile();
|
||||
if (stream && image.LoadFile(*stream)) {
|
||||
i.image = Bitmap(resample(image, 16,16));
|
||||
}
|
||||
items.push_back(i);
|
||||
}
|
||||
vector<PackagedP> choices;
|
||||
package_manager.findMatching(field().match, choices);
|
||||
sort(choices.begin(), choices.end(), ComparePackagePosHint());
|
||||
FOR_EACH(p, choices) {
|
||||
Item i;
|
||||
i.package_name = p->relativeFilename();
|
||||
i.name = capitalize_sentence(p->short_name);
|
||||
Image image;
|
||||
InputStreamP stream = p->openIconFile();
|
||||
if (stream && image.LoadFile(*stream)) {
|
||||
i.image = Bitmap(resample(image, 16,16));
|
||||
}
|
||||
items.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
void PackageChoiceValueViewer::draw(RotatedDC& dc) {
|
||||
drawFieldBorder(dc);
|
||||
// find item
|
||||
String text = value().package_name;
|
||||
Bitmap image;
|
||||
if (value().package_name.empty()) {
|
||||
text = field().empty_name;
|
||||
} else {
|
||||
FOR_EACH(i, items) {
|
||||
if (i.package_name == value().package_name) {
|
||||
text = i.name;
|
||||
image = i.image;
|
||||
}
|
||||
}
|
||||
}
|
||||
// draw image
|
||||
if (image.Ok()) {
|
||||
dc.DrawBitmap(image, RealPoint(0,0));
|
||||
}
|
||||
// draw text
|
||||
dc.SetFont(style().font, 1.0);
|
||||
RealPoint pos = align_in_rect(ALIGN_MIDDLE_LEFT, RealSize(0, dc.GetCharHeight()), dc.getInternalRect()) + RealSize(17., 0);
|
||||
dc.DrawTextWithShadow(text, style().font, pos);
|
||||
drawFieldBorder(dc);
|
||||
// find item
|
||||
String text = value().package_name;
|
||||
Bitmap image;
|
||||
if (value().package_name.empty()) {
|
||||
text = field().empty_name;
|
||||
} else {
|
||||
FOR_EACH(i, items) {
|
||||
if (i.package_name == value().package_name) {
|
||||
text = i.name;
|
||||
image = i.image;
|
||||
}
|
||||
}
|
||||
}
|
||||
// draw image
|
||||
if (image.Ok()) {
|
||||
dc.DrawBitmap(image, RealPoint(0,0));
|
||||
}
|
||||
// draw text
|
||||
dc.SetFont(style().font, 1.0);
|
||||
RealPoint pos = align_in_rect(ALIGN_MIDDLE_LEFT, RealSize(0, dc.GetCharHeight()), dc.getInternalRect()) + RealSize(17., 0);
|
||||
dc.DrawTextWithShadow(text, style().font, pos);
|
||||
}
|
||||
|
||||
@@ -18,20 +18,20 @@
|
||||
/// Viewer that displays a package choice value
|
||||
class PackageChoiceValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(PackageChoice) : ValueViewer(parent,style) { initItems(); }
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
|
||||
struct Item{
|
||||
String package_name;
|
||||
String name;
|
||||
Bitmap image;
|
||||
};
|
||||
DECLARE_VALUE_VIEWER(PackageChoice) : ValueViewer(parent,style) { initItems(); }
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
|
||||
struct Item{
|
||||
String package_name;
|
||||
String name;
|
||||
Bitmap image;
|
||||
};
|
||||
protected:
|
||||
vector<Item> items;
|
||||
vector<Item> items;
|
||||
private:
|
||||
void initItems();
|
||||
struct ComparePackagePosHint;
|
||||
void initItems();
|
||||
struct ComparePackagePosHint;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
+31
-31
@@ -21,38 +21,38 @@ DECLARE_TYPEOF_COLLECTION(SymbolVariationP);
|
||||
IMPLEMENT_VALUE_VIEWER(Symbol);
|
||||
|
||||
void SymbolValueViewer::draw(RotatedDC& dc) {
|
||||
drawFieldBorder(dc);
|
||||
// draw checker background
|
||||
draw_checker(dc, style().getInternalRect());
|
||||
double wh = min(dc.getWidth(), dc.getHeight());
|
||||
// try to load symbol
|
||||
if (symbols.empty() && !value().filename.empty()) {
|
||||
try {
|
||||
// load symbol
|
||||
SymbolP symbol = getLocalPackage().readFile<SymbolP>(value().filename);
|
||||
// aspect ratio
|
||||
double ar = symbol->aspectRatio();
|
||||
ar = min(style().max_aspect_ratio, max(style().min_aspect_ratio, ar));
|
||||
// render and filter variations
|
||||
FOR_EACH(variation, style().variations) {
|
||||
Image img = render_symbol(symbol, *variation->filter, variation->border_radius, int(200 * ar), 200);
|
||||
Image resampled(int(wh * ar), int(wh), false);
|
||||
resample(img, resampled);
|
||||
symbols.push_back(Bitmap(resampled));
|
||||
}
|
||||
} catch (const Error& e) {
|
||||
handle_error(e);
|
||||
}
|
||||
}
|
||||
// draw image, if any
|
||||
int x = 0;
|
||||
for (size_t i = 0 ; i < symbols.size() ; ++i) {
|
||||
// todo : labels?
|
||||
dc.DrawBitmap(symbols[i], RealPoint(x, 0));
|
||||
x += symbols[i].GetWidth() + 2;
|
||||
}
|
||||
drawFieldBorder(dc);
|
||||
// draw checker background
|
||||
draw_checker(dc, style().getInternalRect());
|
||||
double wh = min(dc.getWidth(), dc.getHeight());
|
||||
// try to load symbol
|
||||
if (symbols.empty() && !value().filename.empty()) {
|
||||
try {
|
||||
// load symbol
|
||||
SymbolP symbol = getLocalPackage().readFile<SymbolP>(value().filename);
|
||||
// aspect ratio
|
||||
double ar = symbol->aspectRatio();
|
||||
ar = min(style().max_aspect_ratio, max(style().min_aspect_ratio, ar));
|
||||
// render and filter variations
|
||||
FOR_EACH(variation, style().variations) {
|
||||
Image img = render_symbol(symbol, *variation->filter, variation->border_radius, int(200 * ar), 200);
|
||||
Image resampled(int(wh * ar), int(wh), false);
|
||||
resample(img, resampled);
|
||||
symbols.push_back(Bitmap(resampled));
|
||||
}
|
||||
} catch (const Error& e) {
|
||||
handle_error(e);
|
||||
}
|
||||
}
|
||||
// draw image, if any
|
||||
int x = 0;
|
||||
for (size_t i = 0 ; i < symbols.size() ; ++i) {
|
||||
// todo : labels?
|
||||
dc.DrawBitmap(symbols[i], RealPoint(x, 0));
|
||||
x += symbols[i].GetWidth() + 2;
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolValueViewer::onValueChange() {
|
||||
symbols.clear();
|
||||
symbols.clear();
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
/// Viewer that displays a symbol value
|
||||
class SymbolValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(Symbol) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
void onValueChange();
|
||||
|
||||
DECLARE_VALUE_VIEWER(Symbol) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc);
|
||||
void onValueChange();
|
||||
|
||||
protected:
|
||||
vector<Bitmap> symbols; ///< Cached images
|
||||
vector<Bitmap> symbols; ///< Cached images
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
+16
-16
@@ -15,35 +15,35 @@
|
||||
IMPLEMENT_VALUE_VIEWER(Text);
|
||||
|
||||
bool TextValueViewer::prepare(RotatedDC& dc) {
|
||||
getMask(dc); // ensure alpha/contour mask is loaded
|
||||
return v.prepare(dc, value().value(), style(), viewer.getContext());
|
||||
getMask(dc); // ensure alpha/contour mask is loaded
|
||||
return v.prepare(dc, value().value(), style(), viewer.getContext());
|
||||
}
|
||||
|
||||
void TextValueViewer::draw(RotatedDC& dc) {
|
||||
drawFieldBorder(dc);
|
||||
if (!v.prepared()) {
|
||||
v.prepare(dc, value().value(), style(), viewer.getContext());
|
||||
dc.setStretch(getStretch());
|
||||
}
|
||||
DrawWhat what = viewer.drawWhat(this);
|
||||
v.draw(dc, style(), (DrawWhat)(what & DRAW_ACTIVE));
|
||||
setFieldBorderPen(dc);
|
||||
v.draw(dc, style(), (DrawWhat)(what & ~DRAW_ACTIVE));
|
||||
drawFieldBorder(dc);
|
||||
if (!v.prepared()) {
|
||||
v.prepare(dc, value().value(), style(), viewer.getContext());
|
||||
dc.setStretch(getStretch());
|
||||
}
|
||||
DrawWhat what = viewer.drawWhat(this);
|
||||
v.draw(dc, style(), (DrawWhat)(what & DRAW_ACTIVE));
|
||||
setFieldBorderPen(dc);
|
||||
v.draw(dc, style(), (DrawWhat)(what & ~DRAW_ACTIVE));
|
||||
}
|
||||
|
||||
void TextValueViewer::onValueChange() {
|
||||
v.reset(false);
|
||||
v.reset(false);
|
||||
}
|
||||
|
||||
void TextValueViewer::onStyleChange(int changes) {
|
||||
v.reset(true);
|
||||
ValueViewer::onStyleChange(changes);
|
||||
v.reset(true);
|
||||
ValueViewer::onStyleChange(changes);
|
||||
}
|
||||
|
||||
void TextValueViewer::onAction(const Action&, bool undone) {
|
||||
v.reset(true);
|
||||
v.reset(true);
|
||||
}
|
||||
|
||||
double TextValueViewer::getStretch() const {
|
||||
return v.prepared() ? style().getStretch() : 1.0;
|
||||
return v.prepared() ? style().getStretch() : 1.0;
|
||||
}
|
||||
|
||||
+10
-10
@@ -19,17 +19,17 @@
|
||||
/// Viewer that displays a text value
|
||||
class TextValueViewer : public ValueViewer {
|
||||
public:
|
||||
DECLARE_VALUE_VIEWER(Text) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual bool prepare(RotatedDC& dc);
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onValueChange();
|
||||
virtual void onStyleChange(int);
|
||||
virtual void onAction(const Action&, bool undone);
|
||||
virtual double getStretch() const;
|
||||
|
||||
DECLARE_VALUE_VIEWER(Text) : ValueViewer(parent,style) {}
|
||||
|
||||
virtual bool prepare(RotatedDC& dc);
|
||||
virtual void draw(RotatedDC& dc);
|
||||
virtual void onValueChange();
|
||||
virtual void onStyleChange(int);
|
||||
virtual void onAction(const Action&, bool undone);
|
||||
virtual double getStretch() const;
|
||||
|
||||
protected:
|
||||
TextViewer v;
|
||||
TextViewer v;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+40
-40
@@ -15,81 +15,81 @@ DECLARE_TYPEOF_COLLECTION(wxPoint);
|
||||
// ----------------------------------------------------------------------------- : ValueViewer
|
||||
|
||||
ValueViewer::ValueViewer(DataViewer& parent, const StyleP& style)
|
||||
: StyleListener(style), viewer(parent)
|
||||
: StyleListener(style), viewer(parent)
|
||||
{}
|
||||
|
||||
Package& ValueViewer::getStylePackage() const { return viewer.getStylePackage(); }
|
||||
Package& ValueViewer::getLocalPackage() const { return viewer.getLocalPackage(); }
|
||||
|
||||
void ValueViewer::setValue(const ValueP& value) {
|
||||
assert(value->fieldP == styleP->fieldP); // matching field
|
||||
if (valueP == value) return;
|
||||
valueP = value;
|
||||
onValueChange();
|
||||
assert(value->fieldP == styleP->fieldP); // matching field
|
||||
if (valueP == value) return;
|
||||
valueP = value;
|
||||
onValueChange();
|
||||
}
|
||||
|
||||
bool ValueViewer::containsPoint(const RealPoint& p) const {
|
||||
return getMask().isOpaque(p, styleP->getSize());
|
||||
return getMask().isOpaque(p, styleP->getSize());
|
||||
}
|
||||
RealRect ValueViewer::boundingBox() const {
|
||||
return styleP->getExternalRect().grow(1);
|
||||
return styleP->getExternalRect().grow(1);
|
||||
}
|
||||
|
||||
Rotation ValueViewer::getRotation() const {
|
||||
return Rotation(deg_to_rad(getStyle()->angle), getStyle()->getExternalRect(), 1.0, getStretch());
|
||||
return Rotation(deg_to_rad(getStyle()->angle), getStyle()->getExternalRect(), 1.0, getStretch());
|
||||
}
|
||||
|
||||
bool ValueViewer::setFieldBorderPen(RotatedDC& dc) {
|
||||
if (!getField()->editable) return false;
|
||||
DrawWhat what = viewer.drawWhat(this);
|
||||
if (!(what & DRAW_BORDERS)) return false;
|
||||
dc.SetPen( (what & DRAW_ACTIVE)
|
||||
? wxPen(Color(0,128,255), 1, wxSOLID)
|
||||
: wxPen(Color(128,128,128), 1, wxDOT)
|
||||
);
|
||||
return true;
|
||||
if (!getField()->editable) return false;
|
||||
DrawWhat what = viewer.drawWhat(this);
|
||||
if (!(what & DRAW_BORDERS)) return false;
|
||||
dc.SetPen( (what & DRAW_ACTIVE)
|
||||
? wxPen(Color(0,128,255), 1, wxSOLID)
|
||||
: wxPen(Color(128,128,128), 1, wxDOT)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ValueViewer::drawFieldBorder(RotatedDC& dc) {
|
||||
if (setFieldBorderPen(dc)) {
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
const AlphaMask& alpha_mask = getMask(dc);
|
||||
if (alpha_mask.isLoaded()) {
|
||||
// from mask
|
||||
vector<wxPoint> points;
|
||||
alpha_mask.convexHull(points);
|
||||
if (points.size() < 3) return;
|
||||
FOR_EACH(p, points) p = dc.trPixelNoZoom(RealPoint(p.x,p.y));
|
||||
dc.getDC().DrawPolygon((int)points.size(), &points[0]);
|
||||
} else {
|
||||
// simple rectangle
|
||||
dc.DrawRectangle(dc.getInternalRect().grow(dc.trInvS(1)));
|
||||
}
|
||||
}
|
||||
if (setFieldBorderPen(dc)) {
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
const AlphaMask& alpha_mask = getMask(dc);
|
||||
if (alpha_mask.isLoaded()) {
|
||||
// from mask
|
||||
vector<wxPoint> points;
|
||||
alpha_mask.convexHull(points);
|
||||
if (points.size() < 3) return;
|
||||
FOR_EACH(p, points) p = dc.trPixelNoZoom(RealPoint(p.x,p.y));
|
||||
dc.getDC().DrawPolygon((int)points.size(), &points[0]);
|
||||
} else {
|
||||
// simple rectangle
|
||||
dc.DrawRectangle(dc.getInternalRect().grow(dc.trInvS(1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AlphaMask& ValueViewer::getMask(int w, int h) const {
|
||||
GeneratedImage::Options opts(w, h, &getStylePackage(), &getLocalPackage());
|
||||
return styleP->mask.get(opts);
|
||||
GeneratedImage::Options opts(w, h, &getStylePackage(), &getLocalPackage());
|
||||
return styleP->mask.get(opts);
|
||||
}
|
||||
const AlphaMask& ValueViewer::getMask(const Rotation& rot) const {
|
||||
return getMask((int)rot.trX(styleP->width), (int)rot.trY(styleP->height));
|
||||
return getMask((int)rot.trX(styleP->width), (int)rot.trY(styleP->height));
|
||||
}
|
||||
|
||||
|
||||
void ValueViewer::redraw() {
|
||||
viewer.redraw(*this);
|
||||
viewer.redraw(*this);
|
||||
}
|
||||
|
||||
bool ValueViewer::nativeLook() const {
|
||||
return viewer.nativeLook();
|
||||
return viewer.nativeLook();
|
||||
}
|
||||
bool ValueViewer::isCurrent() const {
|
||||
return viewer.viewerIsCurrent(this);
|
||||
return viewer.viewerIsCurrent(this);
|
||||
}
|
||||
|
||||
void ValueViewer::onStyleChange(int changes) {
|
||||
if (!(changes & CHANGE_ALREADY_PREPARED)) {
|
||||
viewer.redraw(*this);
|
||||
}
|
||||
if (!(changes & CHANGE_ALREADY_PREPARED)) {
|
||||
viewer.redraw(*this);
|
||||
}
|
||||
}
|
||||
|
||||
+74
-74
@@ -27,77 +27,77 @@ DECLARE_POINTER_TYPE(Value);
|
||||
/** A viewer can only display a value, not edit it, ValueEditor is used for that */
|
||||
class ValueViewer : public StyleListener {
|
||||
public:
|
||||
/// Construct a ValueViewer, set the value at a later time
|
||||
ValueViewer(DataViewer& parent, const StyleP& style);
|
||||
virtual ~ValueViewer() {}
|
||||
|
||||
/// Change the associated value
|
||||
void setValue(const ValueP&);
|
||||
/// Return the associated field
|
||||
inline const FieldP& getField() const { return styleP->fieldP; }
|
||||
/// Return the associated style
|
||||
inline const StyleP& getStyle() const { return styleP; }
|
||||
/// Return the associated value
|
||||
inline const ValueP& getValue() const { return valueP; }
|
||||
|
||||
/// Prepare before drawing.
|
||||
/** Should return true if a content property has changed
|
||||
* Scripts are re-updated after preparing if they depend on content properties. */
|
||||
virtual bool prepare(RotatedDC& dc) { return false; };
|
||||
/// Draw this value
|
||||
virtual void draw(RotatedDC& dc) = 0;
|
||||
|
||||
/// Does this field contian the given point?
|
||||
virtual bool containsPoint(const RealPoint& p) const;
|
||||
/// Get a bounding rectangle for this field (including any border it may have)
|
||||
virtual RealRect boundingBox() const;
|
||||
|
||||
/// Rotation to use for drawing this field
|
||||
virtual Rotation getRotation() const;
|
||||
/// Stretch factor
|
||||
virtual double getStretch() const { return 1.0; }
|
||||
|
||||
/// Called when the associated value is changed
|
||||
/** Both when we are associated with another value,
|
||||
* and by default when the value itself changes (called from onAction)
|
||||
*/
|
||||
virtual void onValueChange() {}
|
||||
/// Called when a (scripted) property of the associated style has changed
|
||||
/** Default: redraws the viewer if needed */
|
||||
virtual void onStyleChange(int changes);
|
||||
/// Called when an action is performed on the associated value
|
||||
virtual void onAction(const Action&, bool undone) { onValueChange(); }
|
||||
|
||||
/// Convert this viewer to an editor, if possible
|
||||
virtual ValueEditor* getEditor() { return 0; }
|
||||
|
||||
DataViewer& viewer; ///< Our parent object
|
||||
/// Construct a ValueViewer, set the value at a later time
|
||||
ValueViewer(DataViewer& parent, const StyleP& style);
|
||||
virtual ~ValueViewer() {}
|
||||
|
||||
/// Change the associated value
|
||||
void setValue(const ValueP&);
|
||||
/// Return the associated field
|
||||
inline const FieldP& getField() const { return styleP->fieldP; }
|
||||
/// Return the associated style
|
||||
inline const StyleP& getStyle() const { return styleP; }
|
||||
/// Return the associated value
|
||||
inline const ValueP& getValue() const { return valueP; }
|
||||
|
||||
/// Prepare before drawing.
|
||||
/** Should return true if a content property has changed
|
||||
* Scripts are re-updated after preparing if they depend on content properties. */
|
||||
virtual bool prepare(RotatedDC& dc) { return false; };
|
||||
/// Draw this value
|
||||
virtual void draw(RotatedDC& dc) = 0;
|
||||
|
||||
/// Does this field contian the given point?
|
||||
virtual bool containsPoint(const RealPoint& p) const;
|
||||
/// Get a bounding rectangle for this field (including any border it may have)
|
||||
virtual RealRect boundingBox() const;
|
||||
|
||||
/// Rotation to use for drawing this field
|
||||
virtual Rotation getRotation() const;
|
||||
/// Stretch factor
|
||||
virtual double getStretch() const { return 1.0; }
|
||||
|
||||
/// Called when the associated value is changed
|
||||
/** Both when we are associated with another value,
|
||||
* and by default when the value itself changes (called from onAction)
|
||||
*/
|
||||
virtual void onValueChange() {}
|
||||
/// Called when a (scripted) property of the associated style has changed
|
||||
/** Default: redraws the viewer if needed */
|
||||
virtual void onStyleChange(int changes);
|
||||
/// Called when an action is performed on the associated value
|
||||
virtual void onAction(const Action&, bool undone) { onValueChange(); }
|
||||
|
||||
/// Convert this viewer to an editor, if possible
|
||||
virtual ValueEditor* getEditor() { return 0; }
|
||||
|
||||
DataViewer& viewer; ///< Our parent object
|
||||
protected:
|
||||
ValueP valueP; ///< The value we are currently viewing
|
||||
|
||||
/// Set the pen for drawing the border, returns true if a border needs to be drawn
|
||||
bool setFieldBorderPen(RotatedDC& dc);
|
||||
/// Draws a border around the field
|
||||
void drawFieldBorder(RotatedDC& dc);
|
||||
|
||||
/// Redraw this viewer
|
||||
void redraw();
|
||||
|
||||
/// Load the AlphaMask for this field, scaled but not rotated
|
||||
const AlphaMask& getMask(int w = 0, int h = 0) const;
|
||||
const AlphaMask& getMask(const Rotation& rot) const;
|
||||
|
||||
ValueP valueP; ///< The value we are currently viewing
|
||||
|
||||
/// Set the pen for drawing the border, returns true if a border needs to be drawn
|
||||
bool setFieldBorderPen(RotatedDC& dc);
|
||||
/// Draws a border around the field
|
||||
void drawFieldBorder(RotatedDC& dc);
|
||||
|
||||
/// Redraw this viewer
|
||||
void redraw();
|
||||
|
||||
/// Load the AlphaMask for this field, scaled but not rotated
|
||||
const AlphaMask& getMask(int w = 0, int h = 0) const;
|
||||
const AlphaMask& getMask(const Rotation& rot) const;
|
||||
|
||||
public:
|
||||
/// Should this viewer render using a platform native look?
|
||||
bool nativeLook() const;
|
||||
/// Is this the currently selected viewer?
|
||||
/** Usually only the editor allows selection of viewers */
|
||||
bool isCurrent() const;
|
||||
|
||||
/// The package containing style stuff like images
|
||||
Package& getStylePackage() const;
|
||||
/// The local package for loading/saving files
|
||||
Package& getLocalPackage() const;
|
||||
/// Should this viewer render using a platform native look?
|
||||
bool nativeLook() const;
|
||||
/// Is this the currently selected viewer?
|
||||
/** Usually only the editor allows selection of viewers */
|
||||
bool isCurrent() const;
|
||||
|
||||
/// The package containing style stuff like images
|
||||
Package& getStylePackage() const;
|
||||
/// The local package for loading/saving files
|
||||
Package& getLocalPackage() const;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Utility
|
||||
@@ -113,11 +113,11 @@ class ValueViewer : public StyleListener {
|
||||
public: \
|
||||
Type##ValueViewer(DataViewer& parent, const Type ## StyleP& style)
|
||||
|
||||
#define IMPLEMENT_VALUE_VIEWER(Type) \
|
||||
ValueViewerP Type##Style::makeViewer(DataViewer& parent, const StyleP& thisP) { \
|
||||
assert(thisP.get() == this); \
|
||||
return ValueViewerP(new Type##ValueViewer(parent, static_pointer_cast<Type##Style>(thisP))); \
|
||||
}
|
||||
#define IMPLEMENT_VALUE_VIEWER(Type) \
|
||||
ValueViewerP Type##Style::makeViewer(DataViewer& parent, const StyleP& thisP) { \
|
||||
assert(thisP.get() == this); \
|
||||
return ValueViewerP(new Type##ValueViewer(parent, static_pointer_cast<Type##Style>(thisP))); \
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
Reference in New Issue
Block a user