mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-11 21:49:51 +00:00
e173216d0a
* InsetGraphics::updateInset will interogate lyxrc.display_graphics if params.display == DEFAULT. * Ensure that the "default" display is read to and written from file correctly. Next to do: pass a GraphicsParams struct to the GraphicsCache when adding an image rather tahn just the filename and use this to decide exactly how to display the image. Will therefore be able to strip out the lyxrc stuff from ImageLoader et al. Angus git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@3476 a592a061-630c-0410-9148-cb99ea01b6c8
488 lines
16 KiB
C
488 lines
16 KiB
C
/* This file is part of
|
|
* ======================================================
|
|
*
|
|
* LyX, The Document Processor
|
|
*
|
|
* Copyright 2000-2001 The LyX Team.
|
|
*
|
|
* ======================================================
|
|
*
|
|
* \file FormGraphics.C
|
|
* \author Baruch Even, baruch.even@writeme.com
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "xformsBC.h"
|
|
#include "ControlGraphics.h"
|
|
#include "FormGraphics.h"
|
|
#include "form_graphics.h"
|
|
|
|
#include "xforms_helpers.h"
|
|
#include "input_validators.h"
|
|
#include "debug.h" // for lyxerr
|
|
#include "support/lstrings.h" // for strToDbl & tostr
|
|
#include "support/FileInfo.h"
|
|
#include "support/filetools.h" // for MakeAbsPath etc
|
|
#include "insets/insetgraphicsParams.h"
|
|
#include "lyxrc.h" // for lyxrc.display_graphics
|
|
|
|
using std::endl;
|
|
|
|
namespace {
|
|
|
|
// Bound the number of input characters
|
|
int const SCALE_MAXDIGITS = 3;
|
|
int const WIDTH_MAXDIGITS = 10;
|
|
int const HEIGHT_MAXDIGITS = 10;
|
|
int const ROTATE_MAXCHARS = 4;
|
|
int const FILENAME_MAXCHARS = 1024;
|
|
|
|
} // namespace anon
|
|
|
|
|
|
typedef FormCB<ControlGraphics, FormDB<FD_form_graphics> > base_class;
|
|
|
|
FormGraphics::FormGraphics(ControlGraphics & c)
|
|
: base_class(c, _("Graphics"))
|
|
{}
|
|
|
|
|
|
void FormGraphics::redraw()
|
|
{
|
|
if(form() && form()->visible)
|
|
fl_redraw_form(form());
|
|
else
|
|
return;
|
|
|
|
FL_FORM * outer_form = fl_get_active_folder(dialog_->tabFolder);
|
|
if (outer_form && outer_form->visible)
|
|
fl_redraw_form(outer_form);
|
|
}
|
|
|
|
|
|
void FormGraphics::build()
|
|
{
|
|
dialog_.reset(build_graphics());
|
|
|
|
// Manage the ok, apply, restore and cancel/close buttons
|
|
bc().setOK(dialog_->button_ok);
|
|
// bc().setApply(dialog_->button_apply);
|
|
bc().setCancel(dialog_->button_cancel);
|
|
bc().setRestore(dialog_->button_restore);
|
|
|
|
// the file section
|
|
file_.reset(build_file());
|
|
|
|
fl_set_input_return (file_->input_filename, FL_RETURN_CHANGED);
|
|
fl_set_input_return (file_->input_subcaption, FL_RETURN_CHANGED);
|
|
fl_set_input_return (file_->input_lyxwidth, FL_RETURN_CHANGED);
|
|
fl_set_input_return (file_->input_lyxheight, FL_RETURN_CHANGED);
|
|
fl_set_input_maxchars(file_->input_filename, FILENAME_MAXCHARS);
|
|
|
|
fl_addto_choice(file_->choice_width_lyxwidth, choice_Length_All.c_str());
|
|
fl_addto_choice(file_->choice_width_lyxheight, choice_Length_All.c_str());
|
|
fl_addto_choice(file_->choice_display,
|
|
_(" Default | Monochrome | Grayscale | Color | Do not display "));
|
|
//FIXME: This does not work (always set to monochrome by default. Why? JSpitzm)
|
|
fl_set_choice(file_->choice_display, 1);
|
|
|
|
bc().addReadOnly(file_->button_browse);
|
|
bc().addReadOnly(file_->check_subcaption);
|
|
bc().addReadOnly(file_->choice_display);
|
|
|
|
// the size section
|
|
size_.reset(build_size());
|
|
|
|
fl_set_input_return (size_->input_scale, FL_RETURN_CHANGED);
|
|
fl_set_input_return (size_->input_width, FL_RETURN_CHANGED);
|
|
fl_set_input_return (size_->input_height, FL_RETURN_CHANGED);
|
|
|
|
fl_set_input_maxchars(size_->input_scale, SCALE_MAXDIGITS);
|
|
fl_set_input_maxchars(size_->input_width, WIDTH_MAXDIGITS);
|
|
fl_set_input_maxchars(size_->input_height, HEIGHT_MAXDIGITS);
|
|
|
|
fl_set_input_filter(size_->input_scale, fl_unsigned_float_filter);
|
|
|
|
fl_addto_choice(size_->choice_width_units, choice_Length_All.c_str());
|
|
fl_addto_choice(size_->choice_height_units, choice_Length_All.c_str());
|
|
|
|
bc().addReadOnly(size_->button_default);
|
|
bc().addReadOnly(size_->button_wh);
|
|
bc().addReadOnly(size_->button_scale);
|
|
bc().addReadOnly(size_->check_aspectratio);
|
|
|
|
// the bounding box selection
|
|
bbox_.reset(build_bbox());
|
|
fl_set_input_return (bbox_->input_bb_x0, FL_RETURN_CHANGED);
|
|
fl_set_input_return (bbox_->input_bb_y0, FL_RETURN_CHANGED);
|
|
fl_set_input_return (bbox_->input_bb_x1, FL_RETURN_CHANGED);
|
|
fl_set_input_return (bbox_->input_bb_y1, FL_RETURN_CHANGED);
|
|
|
|
bc().addReadOnly(bbox_->button_getBB);
|
|
bc().addReadOnly(bbox_->button_clip);
|
|
bc().addReadOnly(bbox_->button_draft);
|
|
|
|
string const bb_units = "pt|cm|in";
|
|
fl_addto_choice(bbox_->choice_bb_x0, bb_units.c_str());
|
|
fl_addto_choice(bbox_->choice_bb_y0, bb_units.c_str());
|
|
fl_addto_choice(bbox_->choice_bb_x1, bb_units.c_str());
|
|
fl_addto_choice(bbox_->choice_bb_y1, bb_units.c_str());
|
|
|
|
|
|
// the rotate section
|
|
special_.reset(build_special());
|
|
|
|
fl_set_input_return (special_->input_rotate_angle, FL_RETURN_CHANGED);
|
|
|
|
string const choice_origin =
|
|
"default|" // not important
|
|
"leftTop|leftBottom|leftBaseline|" // lt lb lB
|
|
"center|" // c
|
|
"centerTop|centerBottom|centerBaseline|" // ct cb cB
|
|
"rightTop|rightBottom|rightBaseline|" // rt rb rB
|
|
"referencePoint"; // special
|
|
fl_addto_choice(special_->choice_origin, choice_origin.c_str());
|
|
|
|
fl_set_input_return (special_->input_special, FL_RETURN_CHANGED);
|
|
fl_set_input_maxchars(special_->input_rotate_angle, ROTATE_MAXCHARS);
|
|
fl_set_input_filter(special_->input_rotate_angle, fl_float_filter);
|
|
|
|
// add the different tabfolders
|
|
fl_addto_tabfolder(dialog_->tabFolder, _("File"), file_->form);
|
|
fl_addto_tabfolder(dialog_->tabFolder, _("Size"), size_->form);
|
|
fl_addto_tabfolder(dialog_->tabFolder, _("Bounding Box"), bbox_->form);
|
|
fl_addto_tabfolder(dialog_->tabFolder, _("Extras"), special_->form);
|
|
}
|
|
|
|
|
|
void FormGraphics::apply()
|
|
{
|
|
// Create the parameters structure and fill the data from the dialog.
|
|
InsetGraphicsParams & igp = controller().params();
|
|
igp.filename = getStringFromInput(file_->input_filename);
|
|
if (!controller().bbChanged) // different to the original one?
|
|
igp.bb = string(); // don't write anything
|
|
else {
|
|
string bb;
|
|
if (getStringFromInput(bbox_->input_bb_x0).empty())
|
|
bb = "0 ";
|
|
else
|
|
bb = getLengthFromWidgets(bbox_->input_bb_x0,
|
|
bbox_->choice_bb_x0)+" ";
|
|
if (getStringFromInput(bbox_->input_bb_y0).empty())
|
|
bb += "0 ";
|
|
else
|
|
bb += (getLengthFromWidgets(bbox_->input_bb_y0,
|
|
bbox_->choice_bb_y0)+" ");
|
|
if (getStringFromInput(bbox_->input_bb_x1).empty())
|
|
bb += "0 ";
|
|
else
|
|
bb += (getLengthFromWidgets(bbox_->input_bb_x1,
|
|
bbox_->choice_bb_x1)+" ");
|
|
if (getStringFromInput(bbox_->input_bb_y1).empty())
|
|
bb += "0 ";
|
|
else
|
|
bb += (getLengthFromWidgets(bbox_->input_bb_y1,
|
|
bbox_->choice_bb_y1)+" ");
|
|
igp.bb = bb;
|
|
}
|
|
igp.draft = fl_get_button(bbox_->button_draft);
|
|
igp.clip = fl_get_button(bbox_->button_clip);
|
|
igp.subcaption = fl_get_button(file_->check_subcaption);
|
|
igp.subcaptionText = getStringFromInput(file_->input_subcaption);
|
|
|
|
switch (fl_get_choice(file_->choice_display)) {
|
|
case 1:
|
|
igp.display = InsetGraphicsParams::DEFAULT;
|
|
break;
|
|
case 2:
|
|
igp.display = InsetGraphicsParams::MONOCHROME;
|
|
break;
|
|
case 3:
|
|
igp.display = InsetGraphicsParams::GRAYSCALE;
|
|
break;
|
|
case 4:
|
|
igp.display = InsetGraphicsParams::COLOR;
|
|
break;
|
|
case 5:
|
|
igp.display = InsetGraphicsParams::NONE;
|
|
break;
|
|
}
|
|
|
|
if (fl_get_button(size_->button_default))
|
|
igp.size_type = InsetGraphicsParams::DEFAULT_SIZE;
|
|
else if (fl_get_button(size_->button_wh))
|
|
igp.size_type = InsetGraphicsParams::WH;
|
|
else
|
|
igp.size_type = InsetGraphicsParams::SCALE;
|
|
igp.width = LyXLength(getLengthFromWidgets(size_->input_width,
|
|
size_->choice_width_units));
|
|
igp.height = LyXLength(getLengthFromWidgets(size_->input_height,
|
|
size_->choice_height_units));
|
|
igp.scale = strToInt(getStringFromInput(size_->input_scale));
|
|
igp.keepAspectRatio = fl_get_button(size_->check_aspectratio);
|
|
igp.lyxwidth = LyXLength(getLengthFromWidgets(file_->input_lyxwidth,
|
|
file_->choice_width_lyxwidth));
|
|
igp.lyxheight = LyXLength(getLengthFromWidgets(file_->input_lyxheight,
|
|
file_->choice_width_lyxheight));
|
|
|
|
igp.rotateAngle =
|
|
strToDbl(getStringFromInput(special_->input_rotate_angle));
|
|
while (igp.rotateAngle < 0.0 || igp.rotateAngle > 360.0) {
|
|
if (igp.rotateAngle < 0.0) {
|
|
igp.rotateAngle += 360.0;
|
|
} else if (igp.rotateAngle > 360.0) {
|
|
igp.rotateAngle -= 360.0;
|
|
}
|
|
}
|
|
if (fl_get_choice(special_->choice_origin) > 0)
|
|
igp.rotateOrigin = fl_get_choice_text(special_->choice_origin);
|
|
else
|
|
igp.rotateOrigin = string();
|
|
igp.special = getStringFromInput(special_->input_special);
|
|
igp.testInvariant();
|
|
}
|
|
|
|
|
|
void FormGraphics::update()
|
|
{ string unit = "cm";
|
|
if (lyxrc.default_papersize < 3)
|
|
unit = "in";
|
|
string const defaultUnit = string(unit);
|
|
// Update dialog with details from inset
|
|
InsetGraphicsParams & igp = controller().params();
|
|
fl_set_input(file_->input_filename, igp.filename.c_str());
|
|
// set the bounding box values, if exists. First we need the whole
|
|
// path, because the controller knows nothing about the doc-dir
|
|
lyxerr << "GraphicsUpdate::BoundingBox = " << igp.bb << "\n";
|
|
controller().bbChanged = false;
|
|
if (igp.bb.empty()) {
|
|
string const fileWithAbsPath = MakeAbsPath(igp.filename, OnlyPath(igp.filename));
|
|
string bb = controller().readBB(fileWithAbsPath);
|
|
lyxerr << "file::BoundingBox = " << bb << "\n";
|
|
if (!bb.empty()) {
|
|
// get the values from the file
|
|
// in this case we always have the point-unit
|
|
fl_set_input(bbox_->input_bb_x0, token(bb,' ',0).c_str());
|
|
fl_set_input(bbox_->input_bb_y0, token(bb,' ',1).c_str());
|
|
fl_set_input(bbox_->input_bb_x1, token(bb,' ',2).c_str());
|
|
fl_set_input(bbox_->input_bb_y1, token(bb,' ',3).c_str());
|
|
}
|
|
} else { // get the values from the inset
|
|
controller().bbChanged = true;
|
|
LyXLength anyLength;
|
|
anyLength = LyXLength(token(igp.bb,' ',0));
|
|
updateWidgetsFromLength(bbox_->input_bb_x0,
|
|
bbox_->choice_bb_x0,anyLength,"pt");
|
|
anyLength = LyXLength(token(igp.bb,' ',1));
|
|
updateWidgetsFromLength(bbox_->input_bb_y0,
|
|
bbox_->choice_bb_y0,anyLength,"pt");
|
|
anyLength = LyXLength(token(igp.bb,' ',2));
|
|
updateWidgetsFromLength(bbox_->input_bb_x1,
|
|
bbox_->choice_bb_x1,anyLength,"pt");
|
|
anyLength = LyXLength(token(igp.bb,' ',3));
|
|
updateWidgetsFromLength(bbox_->input_bb_y1,
|
|
bbox_->choice_bb_y1,anyLength,"pt");
|
|
}
|
|
// Update the draft and clip mode
|
|
fl_set_button(bbox_->button_draft, igp.draft);
|
|
fl_set_button(bbox_->button_clip, igp.clip);
|
|
// Update the subcaption check button and input field
|
|
fl_set_button(file_->check_subcaption, igp.subcaption);
|
|
fl_set_input(file_->input_subcaption, igp.subcaptionText.c_str());
|
|
setEnabled(file_->input_subcaption,
|
|
fl_get_button(file_->check_subcaption));
|
|
|
|
switch (igp.display) {
|
|
case InsetGraphicsParams::DEFAULT:
|
|
fl_set_choice(file_->choice_display, 1);
|
|
break;
|
|
case InsetGraphicsParams::MONOCHROME:
|
|
fl_set_choice(file_->choice_display, 2);
|
|
break;
|
|
case InsetGraphicsParams::GRAYSCALE:
|
|
fl_set_choice(file_->choice_display, 3);
|
|
break;
|
|
case InsetGraphicsParams::COLOR:
|
|
fl_set_choice(file_->choice_display, 4);
|
|
break;
|
|
case InsetGraphicsParams::NONE:
|
|
fl_set_choice(file_->choice_display, 5);
|
|
break;
|
|
}
|
|
|
|
updateWidgetsFromLength(size_->input_width,
|
|
size_->choice_width_units,igp.width,defaultUnit);
|
|
updateWidgetsFromLength(size_->input_height,
|
|
size_->choice_height_units,igp.height,defaultUnit);
|
|
fl_set_input(size_->input_scale, tostr(igp.scale).c_str());
|
|
switch (igp.size_type) {
|
|
case InsetGraphicsParams::DEFAULT_SIZE: {
|
|
fl_set_button(size_->button_default,1);
|
|
setEnabled(size_->input_width, 0);
|
|
setEnabled(size_->choice_width_units, 0);
|
|
setEnabled(size_->input_height, 0);
|
|
setEnabled(size_->choice_height_units, 0);
|
|
setEnabled(size_->input_scale, 0);
|
|
break;
|
|
}
|
|
case InsetGraphicsParams::WH: {
|
|
fl_set_button(size_->button_wh, 1);
|
|
setEnabled(size_->input_width, 1);
|
|
setEnabled(size_->choice_width_units, 1);
|
|
setEnabled(size_->input_height, 1);
|
|
setEnabled(size_->choice_height_units, 1);
|
|
setEnabled(size_->input_scale, 0);
|
|
break;
|
|
}
|
|
case InsetGraphicsParams::SCALE: {
|
|
fl_set_button(size_->button_scale, 1);
|
|
setEnabled(size_->input_width, 0);
|
|
setEnabled(size_->choice_width_units, 0);
|
|
setEnabled(size_->input_height, 0);
|
|
setEnabled(size_->choice_height_units, 0);
|
|
setEnabled(size_->input_scale, 1);
|
|
break;
|
|
}
|
|
}
|
|
fl_set_button(size_->check_aspectratio, igp.keepAspectRatio);
|
|
// now the lyx-internally viewsize
|
|
updateWidgetsFromLength(file_->input_lyxwidth,
|
|
file_->choice_width_lyxwidth, igp.lyxwidth,defaultUnit);
|
|
updateWidgetsFromLength(file_->input_lyxheight,
|
|
file_->choice_width_lyxheight, igp.lyxheight,defaultUnit);
|
|
// Update the rotate angle and special commands
|
|
fl_set_input(special_->input_rotate_angle,
|
|
tostr(igp.rotateAngle).c_str());
|
|
if (igp.rotateOrigin.empty())
|
|
fl_set_choice(special_->choice_origin,0);
|
|
else
|
|
fl_set_choice_text(special_->choice_origin,igp.rotateOrigin.c_str());
|
|
fl_set_input(special_->input_special, igp.special.c_str());
|
|
}
|
|
|
|
|
|
namespace {
|
|
|
|
bool isValid(FL_OBJECT * ob)
|
|
{
|
|
string const input = getStringFromInput(ob);
|
|
return input.empty() || isValidLength(input) || isStrDbl(input);
|
|
}
|
|
|
|
} // namespace anon
|
|
|
|
|
|
|
|
ButtonPolicy::SMInput FormGraphics::input(FL_OBJECT * ob, long)
|
|
{
|
|
if (ob == file_->button_browse) {
|
|
// Get the filename from the dialog
|
|
string const in_name = getStringFromInput(file_->input_filename);
|
|
string const out_name = controller().Browse(in_name);
|
|
if (out_name != in_name && !out_name.empty()) {
|
|
fl_set_input(file_->input_filename, out_name.c_str());
|
|
}
|
|
} else if (!controller().bbChanged &&
|
|
((ob == bbox_->input_bb_x0) || (ob == bbox_->input_bb_y0) ||
|
|
(ob == bbox_->input_bb_x1) || (ob == bbox_->input_bb_y1) ||
|
|
(ob == bbox_->choice_bb_x0) || (ob == bbox_->choice_bb_y0) ||
|
|
(ob == bbox_->choice_bb_x1) || (ob == bbox_->choice_bb_y1))) {
|
|
controller().bbChanged = true;
|
|
} else if (ob == size_->button_default) {
|
|
setEnabled(size_->input_width, 0);
|
|
setEnabled(size_->choice_width_units, 0);
|
|
setEnabled(size_->input_height, 0);
|
|
setEnabled(size_->choice_height_units, 0);
|
|
setEnabled(size_->input_scale, 0);
|
|
} else if (ob == size_->button_wh) {
|
|
setEnabled(size_->input_width, 1);
|
|
setEnabled(size_->choice_width_units, 1);
|
|
setEnabled(size_->input_height, 1);
|
|
setEnabled(size_->choice_height_units, 1);
|
|
setEnabled(size_->input_scale, 0);
|
|
} else if (ob == size_->button_scale) {
|
|
setEnabled(size_->input_width, 0);
|
|
setEnabled(size_->choice_width_units, 0);
|
|
setEnabled(size_->input_height, 0);
|
|
setEnabled(size_->choice_height_units, 0);
|
|
setEnabled(size_->input_scale, 1);
|
|
} else if (ob == file_->check_subcaption) {
|
|
setEnabled(file_->input_subcaption,
|
|
fl_get_button(file_->check_subcaption));
|
|
} else if (ob == bbox_->button_getBB) {
|
|
string const filename = getStringFromInput(file_->input_filename);
|
|
if (!filename.empty()) {
|
|
string const fileWithAbsPath = MakeAbsPath(filename, OnlyPath(filename));
|
|
string bb = controller().readBB(fileWithAbsPath);
|
|
lyxerr << "getBB::BoundingBox = " << bb << "\n";
|
|
if (!bb.empty()) {
|
|
fl_set_input(bbox_->input_bb_x0, token(bb,' ',0).c_str());
|
|
fl_set_input(bbox_->input_bb_y0, token(bb,' ',1).c_str());
|
|
fl_set_input(bbox_->input_bb_x1, token(bb,' ',2).c_str());
|
|
fl_set_input(bbox_->input_bb_y1, token(bb,' ',3).c_str());
|
|
}
|
|
controller().bbChanged = false;
|
|
}
|
|
} else if (ob == dialog_->button_help) {
|
|
controller().help();
|
|
}
|
|
|
|
// check if the input is valid
|
|
bool invalid = !isValid(bbox_->input_bb_x0);
|
|
invalid = invalid || !isValid(bbox_->input_bb_x1);
|
|
invalid = invalid || !isValid(bbox_->input_bb_y0);
|
|
invalid = invalid || !isValid(bbox_->input_bb_y1);
|
|
invalid = invalid || !isValid(size_->input_width);
|
|
invalid = invalid || !isValid(size_->input_height);
|
|
invalid = invalid || !isValid(file_->input_lyxwidth);
|
|
invalid = invalid || !isValid(file_->input_lyxheight);
|
|
|
|
// deactivate OK/ Apply buttons and
|
|
// spit out warnings if invalid
|
|
if (ob == bbox_->input_bb_x0
|
|
|| ob == bbox_->input_bb_x1
|
|
|| ob == bbox_->input_bb_y0
|
|
|| ob == bbox_->input_bb_y1
|
|
|| ob == size_->input_width
|
|
|| ob == size_->input_height
|
|
|| ob == file_->input_lyxwidth
|
|
|| ob == file_->input_lyxheight) {
|
|
if (invalid) {
|
|
fl_set_object_label(dialog_->text_warning,
|
|
_("Warning: Invalid Length!"));
|
|
fl_show_object(dialog_->text_warning);
|
|
return ButtonPolicy::SMI_INVALID;
|
|
} else {
|
|
fl_hide_object(dialog_->text_warning);
|
|
}
|
|
}
|
|
|
|
return checkInput();
|
|
}
|
|
|
|
|
|
ButtonPolicy::SMInput FormGraphics::checkInput()
|
|
{
|
|
// Put verifications that the dialog shows some sane values,
|
|
// if not disallow clicking on ok/apply.
|
|
// Possibly use a label in the bottom of the dialog to give the reason.
|
|
ButtonPolicy::SMInput activate = ButtonPolicy::SMI_VALID;
|
|
// We verify now that there is a filename, it exists, it's a file
|
|
// and it's readable.
|
|
string filename = getStringFromInput(file_->input_filename);
|
|
FileInfo file(filename);
|
|
if (filename.empty() || !file.isOK() || !file.exist()
|
|
|| !file.isRegular() || !file.readable()
|
|
)
|
|
activate = ButtonPolicy::SMI_INVALID;
|
|
|
|
return activate;
|
|
}
|
|
|