Author: spitz
Date: Tue Mar  6 08:54:22 2012
New Revision: 40867
URL: http://www.lyx.org/trac/changeset/40867

Log:
Implement a native IPA inset (bug #2591) with instant preview. 

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.

Added:
   lyx-devel/trunk/src/insets/InsetIPA.cpp   (contents, props changed)
   lyx-devel/trunk/src/insets/InsetIPA.h   (contents, props changed)
Modified:
   lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py
   lyx-devel/trunk/lib/ui/stdmenus.inc
   lyx-devel/trunk/src/FuncCode.h
   lyx-devel/trunk/src/LyXAction.cpp
   lyx-devel/trunk/src/Makefile.am
   lyx-devel/trunk/src/Text3.cpp
   lyx-devel/trunk/src/factory.cpp
   lyx-devel/trunk/src/insets/InsetCode.h
   lyx-devel/trunk/src/version.h

Modified: lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py
==============================================================================
--- lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py      Tue Mar  6 00:32:30 2012        
(r40866)
+++ lyx-devel/trunk/lib/lyx2lyx/lyx_2_1.py      Tue Mar  6 08:54:22 2012        
(r40867)
@@ -535,6 +535,44 @@
             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 @@
            [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]],

Modified: lyx-devel/trunk/lib/ui/stdmenus.inc
==============================================================================
--- lyx-devel/trunk/lib/ui/stdmenus.inc Tue Mar  6 00:32:30 2012        (r40866)
+++ lyx-devel/trunk/lib/ui/stdmenus.inc Tue Mar  6 08:54:22 2012        (r40867)
@@ -388,7 +388,7 @@
                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"

Modified: lyx-devel/trunk/src/FuncCode.h
==============================================================================
--- lyx-devel/trunk/src/FuncCode.h      Tue Mar  6 00:32:30 2012        (r40866)
+++ lyx-devel/trunk/src/FuncCode.h      Tue Mar  6 08:54:22 2012        (r40867)
@@ -451,6 +451,7 @@
        LFUN_BUFFER_EXPORT_AS,          // tommaso 20111006
        // 350
        LFUN_CLIPBOARD_PASTE_SIMPLE,    // tommaso, 20111028
+       LFUN_IPA_INSERT,                // spitz, 20120305
 
        LFUN_LASTACTION                 // end of the table
 };

Modified: lyx-devel/trunk/src/LyXAction.cpp
==============================================================================
--- lyx-devel/trunk/src/LyXAction.cpp   Tue Mar  6 00:32:30 2012        (r40866)
+++ lyx-devel/trunk/src/LyXAction.cpp   Tue Mar  6 08:54:22 2012        (r40867)
@@ -542,6 +542,14 @@
  * \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

Modified: lyx-devel/trunk/src/Makefile.am
==============================================================================
--- lyx-devel/trunk/src/Makefile.am     Tue Mar  6 00:32:30 2012        (r40866)
+++ lyx-devel/trunk/src/Makefile.am     Tue Mar  6 08:54:22 2012        (r40867)
@@ -558,6 +558,7 @@
        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 @@
        insets/InsetInclude.h \
        insets/InsetIndex.h \
        insets/InsetInfo.h \
+       insets/InsetIPA.h \
        insets/InsetPreview.h \
        insets/InsetLabel.h \
        insets/InsetLayout.h \

Modified: lyx-devel/trunk/src/Text3.cpp
==============================================================================
--- lyx-devel/trunk/src/Text3.cpp       Tue Mar  6 00:32:30 2012        (r40866)
+++ lyx-devel/trunk/src/Text3.cpp       Tue Mar  6 08:54:22 2012        (r40867)
@@ -1649,6 +1649,7 @@
        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 @@
                    && cur.buffer()->params().branchlist().empty())
                        enable = false;
                break;
+       case LFUN_IPA_INSERT:
+               code = IPA_CODE;
+               break;
        case LFUN_PHANTOM_INSERT:
                code = PHANTOM_CODE;
                break;

Modified: lyx-devel/trunk/src/factory.cpp
==============================================================================
--- lyx-devel/trunk/src/factory.cpp     Tue Mar  6 00:32:30 2012        (r40866)
+++ lyx-devel/trunk/src/factory.cpp     Tue Mar  6 08:54:22 2012        (r40867)
@@ -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 @@
                        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.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 {

Modified: lyx-devel/trunk/src/insets/InsetCode.h
==============================================================================
--- lyx-devel/trunk/src/insets/InsetCode.h      Tue Mar  6 00:32:30 2012        
(r40866)
+++ lyx-devel/trunk/src/insets/InsetCode.h      Tue Mar  6 08:54:22 2012        
(r40867)
@@ -231,6 +231,8 @@
        ///
        SCRIPT_CODE, // 105
        ///
+       IPA_CODE,
+       ///
        INSET_CODE_SIZE
 };
 

Added: lyx-devel/trunk/src/insets/InsetIPA.cpp
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ lyx-devel/trunk/src/insets/InsetIPA.cpp     Tue Mar  6 08:54:22 2012        
(r40867)
@@ -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

Added: lyx-devel/trunk/src/insets/InsetIPA.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ lyx-devel/trunk/src/insets/InsetIPA.h       Tue Mar  6 08:54:22 2012        
(r40867)
@@ -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
+

Modified: lyx-devel/trunk/src/version.h
==============================================================================
--- lyx-devel/trunk/src/version.h       Tue Mar  6 00:32:30 2012        (r40866)
+++ lyx-devel/trunk/src/version.h       Tue Mar  6 08:54:22 2012        (r40867)
@@ -30,7 +30,7 @@
 
 // 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

Reply via email to