#include "InsetSpace.h"
+#include "BufferView.h"
#include "Cursor.h"
#include "Dimension.h"
#include "FuncRequest.h"
+#include "FuncStatus.h"
#include "Length.h"
#include "Lexer.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
-#include "frontends/FontMetrics.h"
-#include "frontends/Painter.h"
-
#include "support/debug.h"
#include "support/docstream.h"
#include "support/gettext.h"
#include "support/lstrings.h"
+#include "frontends/Application.h"
+#include "frontends/FontMetrics.h"
+#include "frontends/Painter.h"
+
using namespace std;
namespace lyx {
-InsetSpace::InsetSpace()
+InsetSpace::InsetSpace(InsetSpaceParams const & params)
+ : params_(params)
{}
-InsetSpace::InsetSpace(InsetSpaceParams par)
-{
- params_.kind = par.kind;
- params_.length = par.length;
-}
-
-
InsetSpaceParams::Kind InsetSpace::kind() const
{
return params_.kind;
InsetSpace::~InsetSpace()
{
- InsetSpaceMailer(*this).hideDialog();
+ hideDialogs("space", this);
}
case InsetSpaceParams::HFILL:
message = _("Horizontal Fill");
break;
+ case InsetSpaceParams::HFILL_PROTECTED:
+ message = _("Protected Horizontal Fill");
+ break;
case InsetSpaceParams::DOTFILL:
message = _("Horizontal Fill (Dots)");
break;
case InsetSpaceParams::HRULEFILL:
message = _("Horizontal Fill (Rule)");
break;
+ case InsetSpaceParams::LEFTARROWFILL:
+ message = _("Horizontal Fill (Left Arrow)");
+ break;
+ case InsetSpaceParams::RIGHTARROWFILL:
+ message = _("Horizontal Fill (Right Arrow)");
+ break;
+ case InsetSpaceParams::UPBRACEFILL:
+ message = _("Horizontal Fill (Up Brace)");
+ break;
+ case InsetSpaceParams::DOWNBRACEFILL:
+ message = _("Horizontal Fill (Down Brace)");
+ break;
case InsetSpaceParams::CUSTOM:
message = support::bformat(_("Horizontal Space (%1$s)"),
params_.length.asDocstring());
switch (cmd.action) {
case LFUN_INSET_MODIFY: {
- InsetSpaceParams params;
- InsetSpaceMailer::string2params(to_utf8(cmd.argument()), params);
- params_.kind = params.kind;
- params_.length = params.length;
+ string2params(to_utf8(cmd.argument()), params_);
break;
}
case LFUN_MOUSE_RELEASE:
- if (!cur.selection())
- InsetSpaceMailer(*this).showDialog(&cur.bv());
+ if (!cur.selection() && cmd.button() == mouse_button::button1)
+ cur.bv().showDialog("space", params2string(params()), this);
break;
default:
}
+bool InsetSpace::getStatus(Cursor & cur, FuncRequest const & cmd,
+ FuncStatus & status) const
+{
+ switch (cmd.action) {
+ // we handle these
+ case LFUN_INSET_MODIFY:
+ if (cmd.getArg(0) == "space") {
+ InsetSpaceParams params;
+ string2params(to_utf8(cmd.argument()), params);
+ status.setOnOff(params_.kind == params.kind);
+ }
+ status.setEnabled(true);
+ return true;
+ default:
+ return Inset::getStatus(cur, cmd, status);
+ }
+}
+
+
+void InsetSpace::edit(Cursor & cur, bool, EntryDirection)
+{
+ cur.bv().showDialog("space", params2string(params()), this);
+}
+
+
+namespace {
+int const arrow_size = 8;
+}
+
+
void InsetSpace::metrics(MetricsInfo & mi, Dimension & dim) const
{
- if (params_.kind == InsetSpaceParams::HFILL ||
- params_.kind == InsetSpaceParams::DOTFILL ||
- params_.kind == InsetSpaceParams::HRULEFILL) {
+ if (isStretchableSpace()) {
// The metrics for this kinds are calculated externally in
// \c TextMetrics::computeRowMetrics. Those are dummy value:
dim = Dimension(10, 10, 10);
dim.wid = int(0.5 * fm.width(char_type('M')));
break;
case InsetSpaceParams::CUSTOM:
- case InsetSpaceParams::CUSTOM_PROTECTED:
- dim.wid = params_.length.inBP();
+ case InsetSpaceParams::CUSTOM_PROTECTED: {
+ int const minwidth = (params_.length.inBP() < 0)
+ ? 3 * arrow_size : 4;
+ dim.wid = max(minwidth, abs(params_.length.inBP()));
break;
+ }
case InsetSpaceParams::HFILL:
+ case InsetSpaceParams::HFILL_PROTECTED:
case InsetSpaceParams::DOTFILL:
case InsetSpaceParams::HRULEFILL:
+ case InsetSpaceParams::LEFTARROWFILL:
+ case InsetSpaceParams::RIGHTARROWFILL:
+ case InsetSpaceParams::UPBRACEFILL:
+ case InsetSpaceParams::DOWNBRACEFILL:
// shut up compiler
break;
}
{
Dimension const dim = dimension(*pi.base.bv);
- if (params_.kind == InsetSpaceParams::HFILL ||
- params_.kind == InsetSpaceParams::DOTFILL ||
- params_.kind == InsetSpaceParams::HRULEFILL) {
+ if (isStretchableSpace() || params_.length.inBP() < 0) {
int const asc = theFontMetrics(pi.base.font).ascent('M');
int const desc = theFontMetrics(pi.base.font).descent('M');
+ // Pixel height divisible by 2 for prettier fill graphics:
+ int const oddheight = (asc ^ desc) & 1;
int const x0 = x + 1;
int const x1 = x + dim.wid - 2;
- int const y0 = y + desc;
- int const y1 = y - asc;
- int const y2 = y - asc / 2;
+ int const y0 = y + desc - 1;
+ int const y1 = y - asc + oddheight - 1;
+ int const y2 = (y0 + y1) / 2;
+ int xoffset = (y0 - y1) / 2;
+
+ // Two tests for very narrow insets
+ if (xoffset > x1 - x0
+ && (params_.kind == InsetSpaceParams::LEFTARROWFILL
+ || params_.kind == InsetSpaceParams::RIGHTARROWFILL))
+ xoffset = x1 - x0;
+ if (xoffset * 6 > (x1 - x0)
+ && (params_.kind == InsetSpaceParams::UPBRACEFILL
+ || params_.kind == InsetSpaceParams::DOWNBRACEFILL))
+ xoffset = (x1 - x0) / 6;
+
+ int const x2 = x0 + xoffset;
+ int const x3 = x1 - xoffset;
+ int const xm = (x0 + x1) / 2;
+ int const xml = xm - xoffset;
+ int const xmr = xm + xoffset;
if (params_.kind == InsetSpaceParams::HFILL) {
pi.pain.line(x0, y1, x0, y0, Color_added_space);
pi.pain.line(x0, y2 , x1, y2, Color_added_space,
frontend::Painter::line_onoffdash);
pi.pain.line(x1, y1, x1, y0, Color_added_space);
+ } else if (params_.kind == InsetSpaceParams::HFILL_PROTECTED) {
+ pi.pain.line(x0, y1, x0, y0, Color_latex);
+ pi.pain.line(x0, y2 , x1, y2, Color_latex,
+ frontend::Painter::line_onoffdash);
+ pi.pain.line(x1, y1, x1, y0, Color_latex);
} else if (params_.kind == InsetSpaceParams::DOTFILL) {
pi.pain.line(x0, y1, x0, y0, Color_special);
- pi.pain.line(x0, y, x1, y, Color_special,
+ pi.pain.line(x0, y0, x1, y0, Color_special,
frontend::Painter::line_onoffdash);
pi.pain.line(x1, y1, x1, y0, Color_special);
- } if (params_.kind == InsetSpaceParams::HRULEFILL) {
+ } else if (params_.kind == InsetSpaceParams::HRULEFILL) {
pi.pain.line(x0, y1, x0, y0, Color_special);
- pi.pain.line(x0, y, x1, y, Color_special);
+ pi.pain.line(x0, y0, x1, y0, Color_special);
pi.pain.line(x1, y1, x1, y0, Color_special);
+ } else if (params_.kind == InsetSpaceParams::LEFTARROWFILL) {
+ pi.pain.line(x2, y1 + 1 , x0 + 1, y2, Color_special);
+ pi.pain.line(x0 + 1, y2 + 1 , x2, y0, Color_special);
+ pi.pain.line(x0, y2 , x1, y2, Color_special);
+ } else if (params_.kind == InsetSpaceParams::RIGHTARROWFILL) {
+ pi.pain.line(x3 + 1, y1 + 1 , x1, y2, Color_special);
+ pi.pain.line(x1, y2 + 1 , x3 + 1, y0, Color_special);
+ pi.pain.line(x0, y2 , x1, y2, Color_special);
+ } else if (params_.kind == InsetSpaceParams::UPBRACEFILL) {
+ pi.pain.line(x0 + 1, y1 + 1 , x2, y2, Color_special);
+ pi.pain.line(x2, y2 , xml, y2, Color_special);
+ pi.pain.line(xml + 1, y2 + 1 , xm, y0, Color_special);
+ pi.pain.line(xm + 1, y0 , xmr, y2 + 1, Color_special);
+ pi.pain.line(xmr, y2 , x3, y2, Color_special);
+ pi.pain.line(x3 + 1, y2 , x1, y1 + 1, Color_special);
+ } else if (params_.kind == InsetSpaceParams::DOWNBRACEFILL) {
+ pi.pain.line(x0 + 1, y0 , x2, y2 + 1, Color_special);
+ pi.pain.line(x2, y2 , xml, y2, Color_special);
+ pi.pain.line(xml + 1, y2 , xm, y1 + 1, Color_special);
+ pi.pain.line(xm + 1, y1 + 1 , xmr, y2, Color_special);
+ pi.pain.line(xmr, y2 , x3, y2, Color_special);
+ pi.pain.line(x3 + 1, y2 + 1 , x1, y0, Color_special);
+ } else if (params_.kind == InsetSpaceParams::CUSTOM) {
+ pi.pain.line(x0, y1 + 1 , x2 + 1, y2, Color_special);
+ pi.pain.line(x2 + 1, y2 + 1 , x0, y0, Color_special);
+ pi.pain.line(x1 + 1, y1 + 1 , x3, y2, Color_special);
+ pi.pain.line(x3, y2 + 1 , x1 + 1, y0, Color_special);
+ pi.pain.line(x2, y2 , x3, y2, Color_special);
+ } else if (params_.kind == InsetSpaceParams::CUSTOM_PROTECTED) {
+ pi.pain.line(x0, y1 + 1 , x2 + 1, y2, Color_latex);
+ pi.pain.line(x2 + 1, y2 + 1 , x0, y0, Color_latex);
+ pi.pain.line(x1 + 1, y1 + 1 , x3, y2, Color_latex);
+ pi.pain.line(x3, y2 + 1 , x1 + 1, y0, Color_latex);
+ pi.pain.line(x2, y2 , x3, y2, Color_latex);
}
return;
}
case InsetSpaceParams::HFILL:
os << "\\hfill{}";
break;
+ case InsetSpaceParams::HFILL_PROTECTED:
+ os << "\\hspace*{\\fill}";
+ break;
case InsetSpaceParams::DOTFILL:
os << "\\dotfill{}";
break;
case InsetSpaceParams::HRULEFILL:
os << "\\hrulefill{}";
break;
+ case InsetSpaceParams::LEFTARROWFILL:
+ os << "\\leftarrowfill{}";
+ break;
+ case InsetSpaceParams::RIGHTARROWFILL:
+ os << "\\rightarrowfill{}";
+ break;
+ case InsetSpaceParams::UPBRACEFILL:
+ os << "\\upbracefill{}";
+ break;
+ case InsetSpaceParams::DOWNBRACEFILL:
+ os << "\\downbracefill{}";
+ break;
case InsetSpaceParams::CUSTOM:
os << "\\hspace{}";
break;
void InsetSpaceParams::read(Lexer & lex)
{
- lex.next();
- string const command = lex.getString();
+ lex.setContext("InsetSpaceParams::read");
+ string command;
+ lex >> command;
if (command == "\\space{}")
kind = InsetSpaceParams::NORMAL;
kind = InsetSpaceParams::NEGTHIN;
else if (command == "\\hfill{}")
kind = InsetSpaceParams::HFILL;
+ else if (command == "\\hspace*{\\fill}")
+ kind = InsetSpaceParams::HFILL_PROTECTED;
else if (command == "\\dotfill{}")
kind = InsetSpaceParams::DOTFILL;
else if (command == "\\hrulefill{}")
kind = InsetSpaceParams::HRULEFILL;
else if (command == "\\hspace{}")
kind = InsetSpaceParams::CUSTOM;
+ else if (command == "\\leftarrowfill{}")
+ kind = InsetSpaceParams::LEFTARROWFILL;
+ else if (command == "\\rightarrowfill{}")
+ kind = InsetSpaceParams::RIGHTARROWFILL;
+ else if (command == "\\upbracefill{}")
+ kind = InsetSpaceParams::UPBRACEFILL;
+ else if (command == "\\downbracefill{}")
+ kind = InsetSpaceParams::DOWNBRACEFILL;
else if (command == "\\hspace*{}")
kind = InsetSpaceParams::CUSTOM_PROTECTED;
else
lex.printError("InsetSpace: Unknown kind: `$$Token'");
-
- string token;
- lex >> token;
- if (token == "\\length") {
- lex.next();
- string const len = lex.getString();
- length = Length(len);
- lex.next();
- token = lex.getString();
- }
- if (!lex)
- return;
- if (token != "\\end_inset")
- lex.printError("Missing \\end_inset at this point. "
- "Read: `$$Token'");
+ if (lex.checkFor("\\length"))
+ lex >> length;
}
void InsetSpace::write(ostream & os) const
{
- os << "Space ";
+ os << "space ";
params_.write(os);
}
void InsetSpace::read(Lexer & lex)
{
params_.read(lex);
+ lex >> "\\end_inset";
}
case InsetSpaceParams::HFILL:
os << (runparams.free_spacing ? " " : "\\hfill{}");
break;
+ case InsetSpaceParams::HFILL_PROTECTED:
+ os << (runparams.free_spacing ? " " : "\\hspace*{\\fill}");
+ break;
case InsetSpaceParams::DOTFILL:
os << (runparams.free_spacing ? " " : "\\dotfill{}");
break;
case InsetSpaceParams::HRULEFILL:
os << (runparams.free_spacing ? " " : "\\hrulefill{}");
break;
+ case InsetSpaceParams::LEFTARROWFILL:
+ os << (runparams.free_spacing ? " " : "\\leftarrowfill{}");
+ break;
+ case InsetSpaceParams::RIGHTARROWFILL:
+ os << (runparams.free_spacing ? " " : "\\rightarrowfill{}");
+ break;
+ case InsetSpaceParams::UPBRACEFILL:
+ os << (runparams.free_spacing ? " " : "\\upbracefill{}");
+ break;
+ case InsetSpaceParams::DOWNBRACEFILL:
+ os << (runparams.free_spacing ? " " : "\\downbracefill{}");
+ break;
case InsetSpaceParams::CUSTOM:
if (runparams.free_spacing)
os << " ";
{
switch (params_.kind) {
case InsetSpaceParams::HFILL:
+ case InsetSpaceParams::HFILL_PROTECTED:
os << " ";
return 5;
case InsetSpaceParams::DOTFILL:
case InsetSpaceParams::HRULEFILL:
os << "_____";
return 5;
+ case InsetSpaceParams::LEFTARROWFILL:
+ os << "<----";
+ return 5;
+ case InsetSpaceParams::RIGHTARROWFILL:
+ os << "---->";
+ return 5;
+ case InsetSpaceParams::UPBRACEFILL:
+ os << "\\-v-/";
+ return 5;
+ case InsetSpaceParams::DOWNBRACEFILL:
+ os << "/-^-\\";
+ return 5;
default:
os << ' ';
return 1;
os << " ";
break;
case InsetSpaceParams::HFILL:
+ case InsetSpaceParams::HFILL_PROTECTED:
os << '\n';
case InsetSpaceParams::DOTFILL:
// FIXME
case InsetSpaceParams::HRULEFILL:
// FIXME
os << '\n';
+ case InsetSpaceParams::LEFTARROWFILL:
+ case InsetSpaceParams::RIGHTARROWFILL:
+ case InsetSpaceParams::UPBRACEFILL:
+ case InsetSpaceParams::DOWNBRACEFILL:
case InsetSpaceParams::CUSTOM:
case InsetSpaceParams::CUSTOM_PROTECTED:
// FIXME
bool InsetSpace::isStretchableSpace() const
{
- return (params_.kind == InsetSpaceParams::HFILL ||
- params_.kind == InsetSpaceParams::DOTFILL ||
- params_.kind == InsetSpaceParams::HRULEFILL);
+ return params_.kind == InsetSpaceParams::HFILL
+ || params_.kind == InsetSpaceParams::HFILL_PROTECTED
+ || params_.kind == InsetSpaceParams::DOTFILL
+ || params_.kind == InsetSpaceParams::HRULEFILL
+ || params_.kind == InsetSpaceParams::LEFTARROWFILL
+ || params_.kind == InsetSpaceParams::RIGHTARROWFILL
+ || params_.kind == InsetSpaceParams::UPBRACEFILL
+ || params_.kind == InsetSpaceParams::DOWNBRACEFILL;
}
-string const InsetSpaceMailer::name_ = "space";
-
-
-InsetSpaceMailer::InsetSpaceMailer(InsetSpace & inset)
- : inset_(inset)
-{}
-
-
-string const InsetSpaceMailer::inset2string(Buffer const &) const
+docstring InsetSpace::contextMenu(BufferView const &, int, int) const
{
- return params2string(inset_.params());
+ return from_ascii("context-space");
}
-void InsetSpaceMailer::string2params(string const & in, InsetSpaceParams & params)
+void InsetSpace::string2params(string const & in, InsetSpaceParams & params)
{
params = InsetSpaceParams();
if (in.empty())
return;
istringstream data(in);
- Lexer lex(0,0);
+ Lexer lex;
lex.setStream(data);
-
- string name;
- lex >> name;
- if (!lex || name != name_)
- return print_mailer_error("InsetSpaceMailer", in, 1, name_);
-
- params.read(lex);
+ lex.setContext("InsetSpace::string2params");
+ lex >> "space";
+
+ // There are cases, such as when we are called via getStatus() from
+ // Dialog::canApply(), where we are just called with "space" rather
+ // than a full "space \type{}\n\\end_inset".
+ if (lex.isOK())
+ params.read(lex);
}
-string const InsetSpaceMailer::params2string(InsetSpaceParams const & params)
+string InsetSpace::params2string(InsetSpaceParams const & params)
{
ostringstream data;
- data << name_ << ' ';
+ data << "space" << ' ';
params.write(data);
return data.str();
}