]> git.lyx.org Git - features.git/commitdiff
Implement a native IPA inset (bug #2591) with instant preview.
authorJürgen Spitzmüller <spitz@lyx.org>
Tue, 6 Mar 2012 07:54:22 +0000 (07:54 +0000)
committerJürgen Spitzmüller <spitz@lyx.org>
Tue, 6 Mar 2012 07:54:22 +0000 (07:54 +0000)
Currently only basic functionality (our math-tipa functionality plus multipar input). Further enhancements (such as proper unicode input and a specific toolbar) are planned. DocBook and XHTML output also need to be audited.

The lyx2lyx reversion routine surely can be improved (help appreciated), and I don't know  tex2lyx enough to handle this file format change.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@40867 a592a061-630c-0410-9148-cb99ea01b6c8

lib/lyx2lyx/lyx_2_1.py
lib/ui/stdmenus.inc
src/FuncCode.h
src/LyXAction.cpp
src/Makefile.am
src/Text3.cpp
src/factory.cpp
src/insets/InsetCode.h
src/insets/InsetIPA.cpp [new file with mode: 0644]
src/insets/InsetIPA.h [new file with mode: 0644]
src/version.h

index dc755f389d8feab6e2b158db5a398382f5eb46ff..470414336586d246b0471a5e9485ffca9c68b4a4 100644 (file)
@@ -535,6 +535,44 @@ def revert_verbatim(document):
             document.body[i:i+1] = subst_begin
 
 
+def revert_tipa(document):
+    " Revert native TIPA insets to mathed or ERT. "
+    i = 0
+    while 1:
+        i = find_token(document.body, "\\begin_inset IPA", i)
+        if i == -1:
+            return
+        j = find_end_of_inset(document.body, i)
+        if j == -1:
+            document.warning("Malformed lyx document: Can't find end of IPA inset")
+            i += 1
+            continue
+        Multipar = False
+        n = find_token(document.body, "\\begin_layout", i, j)
+        if n == -1:
+            document.warning("Malformed lyx document: IPA inset has no embedded layout")
+            i += 1
+            continue
+        m = find_end_of_layout(document.body, n)
+        if m == -1:
+            document.warning("Malformed lyx document: Can't find end of embedded layout")
+            i += 1
+            continue
+        content = document.body[n+1:m]
+        p = find_token(document.body, "\\begin_layout", m, j)
+        if p != -1 or len(content) > 1:
+            Multipar = True
+            content = document.body[i+1:j]
+        if Multipar:
+            # IPA insets with multiple pars need to be wrapped by \begin{IPA}...\end{IPA}
+            document.body[i:j+1] = ['\\end_layout', '', '\\begin_layout Standard'] + put_cmd_in_ert("\\begin{IPA}") + ['\\end_layout'] + content + ['\\begin_layout Standard'] + put_cmd_in_ert("\\end{IPA}")
+            add_to_preamble(document, ["\\usepackage{tipa,tipx}"])
+        else:
+            # single-par IPA insets can be reverted to mathed
+            document.body[i:j+1] = ["\\begin_inset Formula $\\text{\\textipa{" + content[0] + "}}$", "\\end_inset"]
+        i = j
+
+
 ##
 # Conversion hub
 #
@@ -553,10 +591,12 @@ convert = [
            [423, [convert_use_mathtools]],
            [424, [convert_cite_engine_type]],
            [425, []],
-           [426, []]
+           [426, []],
+           [427, []]
           ]
 
 revert =  [
+           [426, [revert_tipa]],
            [425, [revert_verbatim]],
            [424, [revert_cancel]],
            [423, [revert_cite_engine_type]],
index 3762893a289e088670721ccafd2cf6232e4f5e62..6ab91f3a18ccd7cb2bbae546ee367b0aa5c94057 100644 (file)
@@ -388,7 +388,7 @@ Menuset
                Item "Protected Hyphen|y" "specialchar-insert nobreakdash"
                Item "Breakable Slash|a" "specialchar-insert slash"
                Item "Menu Separator|M" "specialchar-insert menu-separator"
-               Item "Phonetic Symbols|P" "command-sequence math-insert \text\textipa ; char-forward ;"
+               Item "Phonetic Symbols|P" "ipa-insert"
        End
 
        Menu "insert_formatting"
index dd60d33cc91f4bbe8477e117f543445aac2e8227..9a7b06e74d6d5775cdc45759cef034e69f113de1 100644 (file)
@@ -451,6 +451,7 @@ enum FuncCode
        LFUN_BUFFER_EXPORT_AS,          // tommaso 20111006
        // 350
        LFUN_CLIPBOARD_PASTE_SIMPLE,    // tommaso, 20111028
+       LFUN_IPA_INSERT,                // spitz, 20120305
 
        LFUN_LASTACTION                 // end of the table
 };
index 59d851c5739936e47f0c673a0448891dcf46d0d8..76ac902b257741e5bebdc5b31bd7c180d1755a38 100644 (file)
@@ -542,6 +542,14 @@ void LyXAction::init()
  * \endvar
  */
                { LFUN_INDEX_PRINT, "index-print", Noop, Edit },
+/*!
+ * \var lyx::FuncCode lyx::LFUN_IPA_INSERT
+ * \li Action: Inserts an IPA inset.
+ * \li Syntax: ipa-insert
+ * \li Origin: spitz, 05 Mar 2012
+ * \endvar
+ */
+        { LFUN_IPA_INSERT, "ipa-insert", Noop, Edit },
 
 /*!
  * \var lyx::FuncCode lyx::LFUN_NOMENCL_INSERT
index a96472fb7037a333f27c9639843e41be7638c837..bfd510ce86e9faf0c6a2d08a16812e3f26015cbb 100644 (file)
@@ -558,6 +558,7 @@ SOURCEFILESINSETS = \
        insets/InsetInclude.cpp \
        insets/InsetIndex.cpp \
        insets/InsetInfo.cpp \
+       insets/InsetIPA.cpp \
        insets/InsetLabel.cpp \
        insets/InsetLayout.cpp \
        insets/InsetLine.cpp \
@@ -614,6 +615,7 @@ HEADERFILESINSETS = \
        insets/InsetInclude.h \
        insets/InsetIndex.h \
        insets/InsetInfo.h \
+       insets/InsetIPA.h \
        insets/InsetPreview.h \
        insets/InsetLabel.h \
        insets/InsetLayout.h \
index ce6811452700f437ba63459a2d9806c3a78c539e..9bb3f256d4d12ceacc2d7f2bb00a6139bbb24ab0 100644 (file)
@@ -1649,6 +1649,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd)
        case LFUN_INDEX_INSERT:
        case LFUN_PREVIEW_INSERT:
        case LFUN_SCRIPT_INSERT:
+       case LFUN_IPA_INSERT:
                // Open the inset, and move the current selection
                // inside it.
                doInsertInset(cur, this, cmd, true, true);
@@ -2445,6 +2446,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd,
                    && cur.buffer()->params().branchlist().empty())
                        enable = false;
                break;
+       case LFUN_IPA_INSERT:
+               code = IPA_CODE;
+               break;
        case LFUN_PHANTOM_INSERT:
                code = PHANTOM_CODE;
                break;
index 737039b0b6011fe8941e2a669fa726930d80c3c3..f17b91dd49c6a81dc95b94a5225b232e6c3fe382 100644 (file)
@@ -38,6 +38,7 @@
 #include "insets/InsetInclude.h"
 #include "insets/InsetIndex.h"
 #include "insets/InsetInfo.h"
+#include "insets/InsetIPA.h"
 #include "insets/InsetLabel.h"
 #include "insets/InsetLine.h"
 #include "insets/InsetMarginal.h"
@@ -184,6 +185,9 @@ Inset * createInsetHelper(Buffer * buf, FuncRequest const & cmd)
                        return new InsetIndex(buf, InsetIndexParams(arg));
                }
 
+               case LFUN_IPA_INSERT:
+                       return new InsetIPA(buf);
+
                case LFUN_NOMENCL_INSERT: {
                        InsetCommandParams icp(NOMENCL_CODE);
                        icp["symbol"] = cmd.argument();
@@ -615,6 +619,8 @@ Inset * readInset(Lexer & lex, Buffer * buf)
                        inset.reset(new InsetFloatList(buf));
                } else if (tmptok == "Info") {
                        inset.reset(new InsetInfo(buf));
+               } else if (tmptok == "IPA") {
+                       inset.reset(new InsetIPA(buf));
                } else if (tmptok == "Preview") {
                        inset.reset(new InsetPreview(buf));
                } else {
index 9bb26d18685b479a561b6df218a7ece6577545fb..ee3a87c160d5325bff632b2ed0bd83eacffa68b1 100644 (file)
@@ -231,6 +231,8 @@ enum InsetCode {
        ///
        SCRIPT_CODE, // 105
        ///
+       IPA_CODE,
+       ///
        INSET_CODE_SIZE
 };
 
diff --git a/src/insets/InsetIPA.cpp b/src/insets/InsetIPA.cpp
new file mode 100644 (file)
index 0000000..482938a
--- /dev/null
@@ -0,0 +1,199 @@
+/**
+ * \file InsetIPA.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+#include "config.h"
+
+#include "InsetIPA.h"
+
+#include "Buffer.h"
+#include "BufferParams.h"
+#include "BufferView.h"
+#include "Cursor.h"
+#include "LaTeXFeatures.h"
+#include "Lexer.h"
+#include "LyXRC.h"
+#include "MetricsInfo.h"
+#include "OutputParams.h"
+#include "RenderPreview.h"
+
+#include "frontends/Painter.h"
+
+#include "graphics/PreviewImage.h"
+
+#include <sstream>
+
+using namespace std;
+
+namespace lyx {
+
+
+InsetIPA::InsetIPA(Buffer * buf) 
+       : InsetText(buf),
+         preview_(new RenderPreview(this)), use_preview_(true)
+{
+       setAutoBreakRows(true);
+       setDrawFrame(true);
+       setFrameColor(Color_insetframe);
+}
+
+
+InsetIPA::~InsetIPA() 
+{}
+
+
+InsetIPA::InsetIPA(InsetIPA const & other)
+       : InsetText(other)
+{
+       preview_.reset(new RenderPreview(*other.preview_, this));
+}
+
+
+void InsetIPA::write(ostream & os) const
+{
+       os << "IPA" << "\n";
+       text().write(os);
+}
+
+
+void InsetIPA::addPreview(DocIterator const & inset_pos,
+       graphics::PreviewLoader &) const
+{
+       preparePreview(inset_pos);
+}
+
+
+void InsetIPA::preparePreview(DocIterator const & pos) const  
+{
+       TexRow texrow;
+       odocstringstream str;  
+       otexstream os(str, texrow);
+       OutputParams runparams(&pos.buffer()->params().encoding());
+       latex(os, runparams);
+       docstring const snippet = str.str();
+       preview_->addPreview(snippet, *pos.buffer());  
+}
+
+
+bool InsetIPA::previewState(BufferView * bv) const
+{
+       if (!editing(bv) && (RenderPreview::status() == LyXRC::PREVIEW_ON ||
+                            RenderPreview::status() == LyXRC::PREVIEW_NO_MATH)) {
+               graphics::PreviewImage const * pimage =
+                       preview_->getPreviewImage(bv->buffer());
+               return pimage && pimage->image();
+       }
+       return false;
+}
+
+
+void InsetIPA::reloadPreview(DocIterator const & pos) const
+{
+       preparePreview(pos);
+       preview_->startLoading(*pos.buffer());
+}
+
+
+void InsetIPA::draw(PainterInfo & pi, int x, int y) const
+{
+       use_preview_ = previewState(pi.base.bv);
+
+       if (use_preview_) {
+               preview_->draw(pi, x + TEXT_TO_INSET_OFFSET, y);
+               setPosCache(pi, x, y);
+               return;
+       }
+       InsetText::draw(pi, x, y);
+}
+
+
+void InsetIPA::edit(Cursor & cur, bool front, EntryDirection entry_from)
+{
+       cur.push(*this);
+       InsetText::edit(cur, front, entry_from);
+}
+
+
+Inset * InsetIPA::editXY(Cursor & cur, int x, int y)
+{
+       if (use_preview_) {
+               edit(cur, true, ENTRY_DIRECTION_IGNORE);
+               return this;
+       }
+       cur.push(*this);
+       return InsetText::editXY(cur, x, y);
+}
+
+
+void InsetIPA::metrics(MetricsInfo & mi, Dimension & dim) const
+{
+       if (previewState(mi.base.bv)) {
+               preview_->metrics(mi, dim);
+               mi.base.textwidth += 2 * TEXT_TO_INSET_OFFSET;
+               
+               dim.wid = max(dim.wid, 4);
+               dim.asc = max(dim.asc, 4);
+               
+               dim.asc += TEXT_TO_INSET_OFFSET;
+               dim.des += TEXT_TO_INSET_OFFSET;
+               dim.wid += TEXT_TO_INSET_OFFSET;
+               dim_ = dim;
+               dim.wid += TEXT_TO_INSET_OFFSET;
+               // insert a one pixel gap
+               dim.wid += 1;
+               // Cache the inset dimension.
+               setDimCache(mi, dim);
+               Dimension dim_dummy;
+               MetricsInfo mi_dummy = mi;
+               InsetText::metrics(mi_dummy, dim_dummy);
+               return;
+       }
+       InsetText::metrics(mi, dim);
+}
+
+
+bool InsetIPA::notifyCursorLeaves(Cursor const & old, Cursor & cur)
+{
+       reloadPreview(old);
+       cur.screenUpdateFlags(Update::Force);
+       return InsetText::notifyCursorLeaves(old, cur);
+}
+
+
+void InsetIPA::validate(LaTeXFeatures & features) const
+{
+       features.require("tipa");
+       features.require("tipx");
+}
+
+
+void InsetIPA::latex(otexstream & os, OutputParams const & runparams) const
+{
+       bool const multipar = (text().paragraphs().size() > 1);
+       if (multipar)
+               os << "\\begin{IPA}\n";
+       else
+               os << "\\textipa{";
+       InsetText::latex(os, runparams);
+       if (multipar)
+               os << "\n\\end{IPA}";
+       else
+               os << "}";
+}
+
+
+bool InsetIPA::insetAllowed(InsetCode code) const
+{
+       if (code == ERT_CODE)
+               return true;
+       else
+               return false;
+}
+
+
+} // namespace lyx
diff --git a/src/insets/InsetIPA.h b/src/insets/InsetIPA.h
new file mode 100644 (file)
index 0000000..09c0e83
--- /dev/null
@@ -0,0 +1,101 @@
+// -*- C++ -*-
+/**
+ * \file InsetIPA.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef INSETIPA_H
+#define INSETIPA_H
+
+#include "InsetText.h"
+
+#include "Dimension.h"
+
+#include <boost/scoped_ptr.hpp>
+
+namespace lyx {
+
+class RenderPreview;
+
+namespace graphics {
+       class PreviewLoader;
+}
+
+/// An IPA inset with instant preview
+class InsetIPA : public InsetText {
+       
+public:
+       ///
+       InsetIPA(Buffer *);
+       ///
+       ~InsetIPA();
+       ///
+       InsetIPA(InsetIPA const & other);
+
+       /// \name Methods inherited from Inset class
+       //@{
+       Inset * clone() const { return new InsetIPA(*this); }
+
+       bool neverIndent() const { return true; }
+       
+       InsetCode lyxCode() const { return IPA_CODE; }
+       
+       docstring layoutName() const { return from_ascii("IPA"); }
+       
+       bool descendable(BufferView const & /*bv*/) const { return true; }
+
+       void metrics(MetricsInfo & mi, Dimension & dim) const;
+
+       Inset * editXY(Cursor & cur, int x, int y);
+
+       void draw(PainterInfo & pi, int x, int y) const;
+
+       void addPreview(DocIterator const & inset_pos,
+               graphics::PreviewLoader & ploader) const;
+
+       bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
+
+       void write(std::ostream & os) const;
+
+       void edit(Cursor & cur, bool front, EntryDirection entry_from);
+       
+       ///
+       void latex(otexstream &, OutputParams const &) const;
+       ///
+       void validate(LaTeXFeatures & features) const;
+       ///
+       bool allowSpellCheck() const { return false; }
+       ///
+       bool insetAllowed(InsetCode code) const;
+       //@}
+       
+protected:
+       /// Retrieves the preview state. Returns true if preview
+       /// is enabled and the preview image is availabled.
+       bool previewState(BufferView * bv) const;
+       /// Recreates the preview if preview is enabled.
+       void reloadPreview(DocIterator const & pos) const;
+       /// Prepare the preview if preview is enabled.
+       void preparePreview(DocIterator const & pos) const;
+
+       ///
+       boost::scoped_ptr<RenderPreview> preview_;
+       ///
+       mutable bool use_preview_;
+
+private:
+       ///
+       mutable Dimension dim_;
+};
+
+
+} // namespace lyx
+
+
+#endif
+
index 9bd5a56aff1f5ada9055e223fa061b529d7298e0..255ca62bcd076705fe3faf8b9eda716dfa64397b 100644 (file)
@@ -30,7 +30,7 @@ extern char const * const lyx_version_info;
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 426 // uwestoehr: support for verbatim
+#define LYX_FORMAT_LYX 427 // spitz: tipa inset
 #define LYX_FORMAT_TEX2LYX 426 // uwestoehr: support for verbatim
 
 #if LYX_FORMAT_FOR_TEX2LYX != LYX_FORMAT_FOR_LYX