/** * This file is part of Archiv-Editor. * * The software Archiv-Editor serves as a client user interface for working with * the Person Data Repository. See: pdr.bbaw.de * * The software Archiv-Editor was developed at the Berlin-Brandenburg Academy * of Sciences and Humanities, Jägerstr. 22/23, D-10117 Berlin. * www.bbaw.de * * Copyright (C) 2010-2013 Berlin-Brandenburg Academy * of Sciences and Humanities * * The software Archiv-Editor was developed by @author: Christoph Plutte. * * Archiv-Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Archiv-Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Archiv-Editor. * If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>. */ package org.bbaw.pdr.ae.view.markup.stext; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.bbaw.pdr.ae.common.AEConstants; import org.bbaw.pdr.ae.common.AEVIEWConstants; import org.bbaw.pdr.ae.common.CommonActivator; import org.bbaw.pdr.ae.config.model.ConfigItem; import org.bbaw.pdr.ae.control.core.PDRConfigProvider; import org.bbaw.pdr.ae.control.facade.Facade; import org.bbaw.pdr.ae.model.Aspect; import org.bbaw.pdr.ae.model.TaggingRange; import org.bbaw.pdr.ae.view.control.interfaces.IMarkupEditor; import org.bbaw.pdr.ae.view.control.provider.MarkupListContentProposalProvider; import org.bbaw.pdr.ae.view.control.provider.MarkupListLabelProvider; import org.bbaw.pdr.ae.view.control.swtnotrwthelper.StyledTextContentAdapter; import org.bbaw.pdr.ae.view.control.swtnotrwthelper.TaggingRangeTransformer; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.bindings.keys.KeyStroke; import org.eclipse.jface.bindings.keys.ParseException; import org.eclipse.jface.fieldassist.ContentProposalAdapter; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.fieldassist.IContentProposal; import org.eclipse.jface.fieldassist.IContentProposalListener; import org.eclipse.jface.resource.FontDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ExtendedModifyEvent; import org.eclipse.swt.custom.ExtendedModifyListener; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseMoveListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; /** * The Class MarkupEditorStext. * @author Christoph Plutte */ public class MarkupEditorStext implements IMarkupEditor { /** The _aspect. */ private Aspect _aspect; /** The _composite. */ private Composite _composite; /** The _title. */ private String _title; /** The _stext. */ private StyledText _stext; /** The _selected tr. */ private TaggingRange[] _selectedTRs; /** The _tr transformer. */ private TaggingRangeTransformer _trTransformer = new TaggingRangeTransformer(); /** The _font descriptor. */ private FontDescriptor _fontDescriptor = FontDescriptor.createFrom("Tahoma", 10, SWT.ROMAN); //$NON-NLS-1$ /** Resource Manager for colors and fonts. */ private LocalResourceManager _resources = new LocalResourceManager(JFaceResources.getResources()); /** The _markup listeners. */ private ArrayList<Listener> _markupListeners = new ArrayList<Listener>(); /** The _modify listeners. */ private ArrayList<Listener> _modifyListeners = new ArrayList<Listener>(); /** The _focus listeners. */ private ArrayList<Listener> _focusListeners = new ArrayList<Listener>(); /** The _key listeners. */ private ArrayList<Listener> _keyListeners = new ArrayList<Listener>(); /** The _text selection listeners. */ private ArrayList<Listener> _textSelectionListeners = new ArrayList<Listener>(); /** The markup provider. */ private String _markupProvider = Platform .getPreferencesService() .getString(CommonActivator.PLUGIN_ID, "PRIMARY_TAGGING_PROVIDER", AEConstants.TAGGING_LIST_PROVIDER, null).toUpperCase(); //$NON-NLS-1$; private Facade _facade = Facade.getInstanz(); private boolean _loaded; @Override public final void addExtendedModifyListener(final Listener extendedModifyListener) { if (extendedModifyListener != null) { _modifyListeners.add(extendedModifyListener); } } @Override public final void addFocusListener(final Listener focusListener) { if (focusListener != null) { _focusListeners.add(focusListener); } } @Override public final void addKeyListener(final Listener keyListener) { if (keyListener != null) { _keyListeners.add(keyListener); } } @Override public final void addMarkupSelectionListener(final Listener listener) { if (listener != null) { _markupListeners.add(listener); } } @Override public final void addTextSelectionListener(final Listener listener) { if (listener != null) { _textSelectionListeners.add(listener); } } @Override public final void createEditor() { _stext = new StyledText(_composite, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER); GridData gd = new GridData(); gd.grabExcessHorizontalSpace = true; gd.horizontalAlignment = SWT.FILL; gd.grabExcessVerticalSpace = true; gd.verticalAlignment = SWT.FILL; // gd.widthHint = 280; gd.heightHint = 50; _stext.setLayoutData(gd); _stext.setFont(_resources.createFont(_fontDescriptor)); //$NON-NLS-1$ // PlatformUI.getWorkbench().getHelpSystem().setHelp(_stext, "org.bbaw.pdr.ae.help.notificationText"); //$NON-NLS-1$ final ControlDecoration decoNoti = new ControlDecoration(_stext, SWT.LEFT | SWT.TOP); _stext.addExtendedModifyListener(new ExtendedModifyListener() { public void modifyText(ExtendedModifyEvent event) { String modi = event.replacedText; Event se = new Event(); se.data = modi; for (Listener s : _modifyListeners) { s.handleEvent(se); } } }); _stext.addMouseMoveListener(new MouseMoveListener() { @Override public void mouseMove(final MouseEvent e) { Point p = new Point(e.x, e.y); boolean hit = false; if (p != null) { try { int offset = _stext.getOffsetAtLocation(p); if (offset >= 1 && offset <= _stext.getText().length()) { if (_stext.getStyleRangeAtOffset(offset) != null || _stext.getStyleRangeAtOffset(offset - 1) != null) { StyleRange ss = _stext.getStyleRangeAtOffset(offset); if (ss != null) { TaggingRange tr = (TaggingRange) ss.data; _selectedTRs = new TaggingRange[] {tr}; hit = true; } else { _selectedTRs = null; } Event se = new Event(); se.data = _selectedTRs; se.x = e.x; se.y = e.y; se.type = SWT.MouseHover; for (Listener s : _markupListeners) { s.handleEvent(se); } } } } catch (IllegalArgumentException ex) { } } if (!hit) { Event se = new Event(); se.data = null; se.x = e.x; se.y = e.y; se.type = SWT.MouseHover; for (Listener s : _markupListeners) { s.handleEvent(se); } } } }); _stext.addMouseListener(new MouseAdapter() { public void mouseDown(MouseEvent e) { // System.out.println("mousListner offsett: " + offset); handleSelection(); } }); _stext.addFocusListener(new FocusListener() { @Override public void focusLost(FocusEvent e) { saveChanges(); Event se = new Event(); se.doit = false; for (Listener l : _focusListeners) { l.handleEvent(se); } } @Override public void focusGained(FocusEvent e) { Event se = new Event(); se.doit = true; for (Listener l : _focusListeners) { l.handleEvent(se); } } }); _stext.addKeyListener(new KeyListener() { @Override public void keyPressed(final KeyEvent e) { } @Override public void keyReleased(final KeyEvent e) { if (_stext.getText().trim().length() > 0) { decoNoti.setImage(null); } else { decoNoti.setImage(FieldDecorationRegistry.getDefault() .getFieldDecoration(FieldDecorationRegistry.DEC_REQUIRED).getImage()); } handleSelection(); } }); _stext.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(final SelectionEvent e) { } @Override public void widgetSelected(final SelectionEvent e) { handleSelection(); // } } }); KeyStroke keyStroke; try { keyStroke = KeyStroke.getInstance("Ctrl+Space"); System.out.println("contentProposal"); ContentProposalAdapter adapter = new ContentProposalAdapter(_stext, new StyledTextContentAdapter(), new MarkupListContentProposalProvider(_facade.getConfigs().get(_markupProvider), false), keyStroke, null); adapter.setLabelProvider(new MarkupListLabelProvider()); adapter.addContentProposalListener(new IContentProposalListener() { @Override public void proposalAccepted(final IContentProposal proposal) { if (proposal instanceof ConfigItem) { ConfigItem ci = (ConfigItem) proposal; ConfigItem ciParent; ConfigItem ciGrandParent; ConfigItem ciGreatGrandParent; String name; String type = null; String subtype = null; String role = null; // String ana = _currentPerson.getPdrId().toString(); if (ci.getParent() != null) { if (ci.getParent() instanceof ConfigItem) { ciParent = (ConfigItem) ci.getParent(); if (ciParent.getParent() != null) { if (ciParent.getParent() instanceof ConfigItem) { ciGrandParent = (ConfigItem) ciParent.getParent(); if (ciGrandParent.getParent() != null) { if (ciGrandParent.getParent() instanceof ConfigItem) { ciGreatGrandParent = (ConfigItem) ciGrandParent.getParent(); name = ciGreatGrandParent.getValue(); type = ciGrandParent.getValue(); subtype = ciParent.getValue(); role = ci.getValue(); } else { name = ciGrandParent.getParent().getValue(); type = ciGrandParent.getValue(); subtype = ciParent.getValue(); role = ci.getValue(); } } else { name = ciGrandParent.getValue(); type = ciParent.getValue(); subtype = ci.getValue(); } } else { name = ciParent.getParent().getValue(); type = ciParent.getValue(); subtype = ci.getValue(); } } else { name = ciParent.getValue(); type = ci.getValue(); } } else { name = ci.getParent().getValue(); type = ci.getValue(); } } else { name = ci.getValue(); } if (name.startsWith("aodl:")) { name = name.substring(5); } if (name.length() > 0 && type.length() > 0) { TaggingRange tr = new TaggingRange(name, type, subtype, role, null, null); String content = PDRConfigProvider.getLabelOfMarkup(name, type, subtype, role); int start = 0; start = _stext.getCaretOffset(); // System.out.println(_stext.getSelectionText()); tr.setStart(start); tr.setLength(content.length()); tr.setTextValue(content); insertContentSetMarkup(tr); for (TaggingRange t : _aspect.getRangeList()) { if (t.getStart() > start) { t.setStart(t.getStart() + content.length()); } } _aspect.getRangeList().add(tr); Collections.sort(_aspect.getRangeList()); _stext.setSelection(start + content.length()); // System.out.println(proposal.getContent()); } } } }); } catch (ParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } protected void handleSelection() { int start = _stext.getSelection().x; int end = _stext.getSelection().y; _selectedTRs = null; if (start <= end && start >= 0 && end <= _stext.getCharCount()) { StyleRange[] ss; if (start == end && start < _stext.getCharCount() && _stext.getStyleRangeAtOffset(start) != null) { ss = new StyleRange[] {_stext.getStyleRangeAtOffset(start)}; } else { ss = _stext.getStyleRanges(start, end - start); } if (ss != null && ss.length > 0) { ArrayList<TaggingRange> trs = new ArrayList<TaggingRange>(ss.length); for (StyleRange s : ss) { if (s != null) { TaggingRange tr = (TaggingRange) s.data; trs.add(tr); } } _selectedTRs = (TaggingRange[]) trs.toArray(new TaggingRange[trs.size()]); } Event se = new Event(); se.data = _selectedTRs; se.type = SWT.KeyUp; for (Listener s : _markupListeners) { s.handleEvent(se); } if (_selectedTRs == null) { String text = _stext.getText().substring(start, end); if (text == null || text.trim().length() > 0) { se.data = text; } else { se.data = null; } for (Listener s : _textSelectionListeners) { s.handleEvent(se); } } } } @Override public void saveChanges() { if (_aspect != null && _loaded) { if (_aspect.getRangeList() != null) { processStyleRanges(); } _aspect.setNotification(_stext.getText()); } } private void processStyleRanges() { TaggingRange tr; List<TaggingRange> processedRanges = new ArrayList<TaggingRange>(); for (StyleRange sr : _stext.getStyleRanges()) { if (sr.data != null && sr.data instanceof TaggingRange && sr.length > 0) { tr = (TaggingRange) sr.data; tr.setStart(sr.start); tr.setLength(sr.length); tr.setTextValue(_stext.getText(sr.start, sr.start + sr.length - 1)); processedRanges.add(tr); } } _aspect.getRangeList().clear(); _aspect.getRangeList().addAll(processedRanges); Collections.sort(_aspect.getRangeList()); } @Override public final void deleteMarkup(final TaggingRange[] taggingRanges) { if (taggingRanges != null) { for (TaggingRange tr : taggingRanges) { if (_stext.getStyleRangeAtOffset(tr.getStart()) != null) { _stext.setStyleRange(new StyleRange(tr.getStart(), tr.getLength(), null, null)); } } } } @Override public final Aspect getAspect() { return _aspect; } @Override public final Control getControl() { return _stext; } @Override public final TaggingRange[] getSelectedMarkups() { return _selectedTRs; } @Override public final String getTitle() { return _title; } @Override public final void insertContentSetMarkup(final TaggingRange tr) { if (tr.getType() != null && tr.getType().trim().length() > 0 && tr.getTextValue().trim().length() > 0) { StyleRange sr = new StyleRange(); sr.data = tr; sr.start = _stext.getSelection().x; tr.setStart(sr.start); sr.length = tr.getTextValue().trim().length(); tr.setLength(sr.length); sr.background = _trTransformer.chooseColor(tr.getName()); _stext.insert(tr.getTextValue()); _stext.setStyleRange(sr); _stext.setSelection(sr.start + sr.length, sr.start + sr.length); _aspect.getRangeList().add(tr); Collections.sort(_aspect.getRangeList()); } } @Override public final boolean isValid() { return _stext.getText().trim().length() > 0; } /** * Load values. */ private void loadValues() { _loaded = false; if (_aspect.getNotification() != null) { _stext.setText(_aspect.getNotification()); } // Tagging LinkedList<TaggingRange> rangeList; StyleRange sr; if (_aspect.getRangeList() != null) { rangeList = (LinkedList<TaggingRange>) _aspect.getRangeList(); for (TaggingRange tr : rangeList) { // System.out.println(tr.getStyleRange().start); // System.out.println(tr.getStart()); // System.out.println(tr.getLength()); // System.out.println(styledTextAspect.getText().length()); if (tr != null) { if (tr.getStart() < _aspect.getNotification().length() && tr.getStart() + tr.getLength() < _aspect.getNotification().length()) { sr = _trTransformer.transformStyleRange(tr); sr.data = tr; _stext.setStyleRange(sr); } else if (tr.getStart() < _aspect.getNotification().length()) { sr = _trTransformer.transformStyleRange(tr); sr.length = _aspect.getNotification().length() - tr.getStart(); sr.data = tr; _stext.setStyleRange(sr); } } } } else { rangeList = new LinkedList<TaggingRange>(); } _loaded = true; } @Override public final void setAspect(final Aspect aspect) { this._aspect = aspect; if (_aspect != null) { loadValues(); } } @Override public final void setComposite(final Composite composite) { this._composite = composite; } @Override public final void setEditable(final boolean editable) { _stext.setEditable(editable); } @Override public final void setFont(final FontDescriptor fontDescriptor) { this._fontDescriptor = fontDescriptor; } @Override public final void setMarkup(final TaggingRange taggingRange) { int start = _stext.getSelection().x; int end = _stext.getSelectionCount() - 1 + start; if (end < start) { end = start; } if (_stext.getSelectionRange().y > 0) { int selectionStart = _stext.getSelectionRange().x; int selectionEnd = selectionStart + _stext.getSelectionRange().y; if (_aspect.getRangeList() != null && _aspect.getRangeList().size() > 0) { for (TaggingRange currentTaggingRange : _aspect.getRangeList()) { int styleRangeStart = currentTaggingRange.getStart(); int styleRangeEnd = styleRangeStart + currentTaggingRange.getLength(); if (selectionStart < styleRangeStart && selectionEnd > styleRangeStart) { /* * Selection ueberlappt Anfang der StyleRange (oder auch * Anfang und Ende) */ start = selectionStart; end = styleRangeStart; break; } else if (selectionStart < styleRangeEnd && selectionEnd > styleRangeEnd) { /* Selection ueberlappt Ende der StyleRange */ start = styleRangeEnd; end = selectionEnd; break; } } } } String selectedText = _stext.getText(start, end); while (selectedText.startsWith(" ")) { selectedText = selectedText.substring(1); start++; } while (selectedText.endsWith(" ")) { selectedText = selectedText.substring(0, selectedText.length() - 1); end--; } taggingRange.setStart(start); taggingRange.setLength(end - start + 1); if (_stext.getText().length() >= end) { taggingRange.setTextValue(_stext.getText(start, end)); } else { taggingRange.setTextValue(_stext.getText(start, _stext.getText().length())); } StyleRange sr = _trTransformer.transformStyleRange(taggingRange); sr.data = taggingRange; if (sr != null) { if (sr.start >= 0 && sr.length + sr.start <= _stext.getText().length()) { _stext.setStyleRange(sr); } else if (sr.length + sr.start <= _stext.getText().length()) { taggingRange.setLength(_stext.getText().length() - taggingRange.getStart()); sr.length = _stext.getText().length() - sr.start; try { _stext.setStyleRange(sr); } finally { // nothing } } } _stext.setSelection(sr.start + sr.length, sr.start + sr.length); } @Override public final void setTitle(final String title) { this._title = title; } @Override public void refresh() { int caret = _stext.getCaretOffset(); loadValues(); _stext.setCaretOffset(Math.min(caret, _stext.getTextLimit())); } @Override public void insert(String string) { _stext.insert(string); _stext.setSelection(_stext.getSelection().x + string.length()); } @Override public void setSelected(boolean selected) { if (selected) { if (!_stext.isDisposed()) { _stext.setForeground(AEVIEWConstants.VIEW_FOREGROUND_SELECTED_COLOR); } } else { if (!_stext.isDisposed()) {_stext.setForeground(AEVIEWConstants.VIEW_FOREGROUND_DESELECTED_COLOR); } } } @Override public void setFocus() { _stext.setFocus(); } @Override public String getSelectionText() { return _stext.getSelectionText(); } }