PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/org.xmind.ui.toolkit/src/org/xmind/ui/richtext/RichTextUtils.java

https://bitbucket.org/eug48/xmind3-releases-mirror
Java | 823 lines | 640 code | 91 blank | 92 comment | 197 complexity | 725d3468fed819ba5043b0c78ffb1c81 MD5 | raw file
  1. /* ******************************************************************************
  2. * Copyright (c) 2006-2010 XMind Ltd. and others.
  3. *
  4. * This file is a part of XMind 3. XMind releases 3 and
  5. * above are dual-licensed under the Eclipse Public License (EPL),
  6. * which is available at http://www.eclipse.org/legal/epl-v10.html
  7. * and the GNU Lesser General Public License (LGPL),
  8. * which is available at http://www.gnu.org/licenses/lgpl.html
  9. * See http://www.xmind.net/license.html for details.
  10. *
  11. * Contributors:
  12. * XMind Ltd. - initial API and implementation
  13. *******************************************************************************/
  14. package org.xmind.ui.richtext;
  15. import static org.xmind.ui.richtext.ImagePlaceHolder.PLACE_HOLDER;
  16. import java.util.ArrayList;
  17. import java.util.Arrays;
  18. import java.util.List;
  19. import org.eclipse.jface.resource.JFaceResources;
  20. import org.eclipse.jface.text.BadLocationException;
  21. import org.eclipse.jface.text.IDocument;
  22. import org.eclipse.jface.text.IRegion;
  23. import org.eclipse.jface.text.TextViewer;
  24. import org.eclipse.jface.util.Util;
  25. import org.eclipse.swt.SWT;
  26. import org.eclipse.swt.custom.StyleRange;
  27. import org.eclipse.swt.graphics.Color;
  28. import org.eclipse.swt.graphics.Font;
  29. import org.eclipse.swt.graphics.FontData;
  30. import org.eclipse.swt.graphics.TextStyle;
  31. import org.eclipse.swt.widgets.Display;
  32. import org.xmind.ui.resources.FontUtils;
  33. /**
  34. * @author Frank Shaka
  35. */
  36. public class RichTextUtils {
  37. static final String LineDelimiter = System.getProperty("line.separator"); //$NON-NLS-1$
  38. public static Font DEFAULT_FONT = JFaceResources.getDefaultFont();
  39. public static FontData DEFAULT_FONT_DATA = DEFAULT_FONT.getFontData()[0];
  40. public static Color DEFAULT_FOREGROUND = Display.getCurrent()
  41. .getSystemColor(SWT.COLOR_LIST_FOREGROUND);
  42. public static Color DEFAULT_BACKGROUND = Display.getCurrent()
  43. .getSystemColor(SWT.COLOR_LIST_BACKGROUND);
  44. public static final char INDENT_CHAR = '\t';
  45. public static final String EMPTY = ""; //$NON-NLS-1$
  46. public static final StyleRange DEFAULT_STYLE = new StyleRange();
  47. public static final LineStyle DEFAULT_LINE_STYLE = new LineStyle();
  48. private RichTextUtils() {
  49. }
  50. public static boolean isItalic(StyleRange style) {
  51. return hasFontStyle(style, SWT.ITALIC);
  52. }
  53. public static boolean setItalic(StyleRange style, boolean italic) {
  54. return changeFontStyle(style, SWT.ITALIC, italic);
  55. }
  56. public static boolean isBold(StyleRange style) {
  57. return hasFontStyle(style, SWT.BOLD);
  58. }
  59. public static boolean setBold(StyleRange style, boolean bold) {
  60. return changeFontStyle(style, SWT.BOLD, bold);
  61. }
  62. public static boolean hasFontStyle(StyleRange style, int singleStyle) {
  63. return (getFontStyle(style) & singleStyle) != 0;
  64. }
  65. public static boolean changeFontStyle(StyleRange style, int singleStyle,
  66. boolean value) {
  67. int fontStyle = getFontStyle(style);
  68. int changedFontStyle = getChangedFontStyle(fontStyle, singleStyle,
  69. value);
  70. if (fontStyle == changedFontStyle)
  71. return false;
  72. setFontStyle(style, changedFontStyle);
  73. return true;
  74. }
  75. public static int getChangedFontStyle(int fontStyle, int singleStyle,
  76. boolean value) {
  77. if (value) {
  78. fontStyle |= singleStyle;
  79. } else {
  80. fontStyle &= ~singleStyle;
  81. }
  82. return fontStyle;
  83. }
  84. public static int getFontStyle(StyleRange style) {
  85. return style.font == null ? style.fontStyle
  86. : style.font.getFontData()[0].getStyle();
  87. }
  88. public static void setFontStyle(StyleRange style, int fontStyle) {
  89. style.fontStyle = fontStyle;
  90. if (style.font != null) {
  91. style.font = FontUtils.getStyled(style.font, fontStyle);
  92. // if ((fontStyle & SWT.BOLD) != 0) {
  93. // style.font = FontUtils.getBold(style.font);
  94. // }
  95. // if ((fontStyle & SWT.ITALIC) != 0) {
  96. // style.font = FontUtils.getItalic(style.font);
  97. // }
  98. }
  99. }
  100. public static int getFontStyle(boolean bold, boolean italic) {
  101. int fontStyle = SWT.NORMAL;
  102. if (bold)
  103. fontStyle |= SWT.BOLD;
  104. if (italic)
  105. fontStyle |= SWT.ITALIC;
  106. return fontStyle;
  107. }
  108. public static String getFontFace(StyleRange style) {
  109. return getFont(style).getFontData()[0].getName();
  110. }
  111. public static int getFontSize(StyleRange style) {
  112. return getFont(style).getFontData()[0].getHeight();
  113. }
  114. public static Font getFont(StyleRange style) {
  115. return style.font == null ? DEFAULT_FONT : style.font;
  116. }
  117. public static Color getForeground(StyleRange style) {
  118. return style.foreground == null ? DEFAULT_FOREGROUND : style.foreground;
  119. }
  120. public static Color getBackground(StyleRange style) {
  121. return style.background == null ? DEFAULT_BACKGROUND : style.background;
  122. }
  123. public static boolean setFont(StyleRange style, Font font) {
  124. if (font == style.font || (font != null && equals(font, style.font)))
  125. return false;
  126. style.font = font;
  127. return true;
  128. }
  129. public static boolean setFontFace(StyleRange style, String name) {
  130. if (name == null) {
  131. name = DEFAULT_FONT_DATA.getName();
  132. }
  133. if (getFontFace(style).equals(name)) {
  134. return false;
  135. }
  136. style.font = FontUtils.getNewName(getFont(style), name);
  137. return true;
  138. }
  139. public static boolean setFontSize(StyleRange style, int size) {
  140. if (size <= 0) {
  141. size = DEFAULT_FONT_DATA.getHeight();
  142. }
  143. if (getFontSize(style) == size)
  144. return false;
  145. style.font = FontUtils.getNewHeight(getFont(style), size);
  146. return true;
  147. }
  148. public static boolean setForeground(StyleRange style, Color color) {
  149. if (color == style.foreground
  150. || (color != null && color.equals(style.foreground)))
  151. return false;
  152. style.foreground = color;
  153. return true;
  154. }
  155. public static boolean setBackground(StyleRange style, Color color) {
  156. if (color == style.background
  157. || (color != null && color.equals(style.background)))
  158. return false;
  159. style.background = color;
  160. return true;
  161. }
  162. public static List<Hyperlink> getHyperlinksInRange(Hyperlink[] hyperlinks,
  163. int start, int end) {
  164. List<Hyperlink> results = new ArrayList<Hyperlink>(hyperlinks.length);
  165. for (Hyperlink hyperlink : hyperlinks) {
  166. if (hyperlink.start <= end && hyperlink.end() >= start) {
  167. results.add(hyperlink);
  168. }
  169. }
  170. return results;
  171. }
  172. public static LineStyle updateLineStylePositions(int startLine,
  173. int oldLineCount, int newLineCount, List<LineStyle> lineStyles,
  174. IDocument document) {
  175. int oldEndLine = startLine + oldLineCount;
  176. int deltaLines = newLineCount - oldLineCount;
  177. LineStyle firstInRange = null;
  178. int firstInRangeIndex = 0;
  179. for (int i = 0; i < lineStyles.size();) {
  180. LineStyle current = lineStyles.get(i);
  181. int currentLineIndex = current.lineIndex;
  182. if (currentLineIndex == 0) {
  183. String content = document.get();
  184. if ("".equals(content)) //$NON-NLS-1$
  185. current.bulletStyle = LineStyle.NONE_STYLE;
  186. }
  187. if (currentLineIndex < startLine) {
  188. i++;
  189. continue;
  190. }
  191. if (currentLineIndex >= oldEndLine) {
  192. current.lineIndex += deltaLines;
  193. i++;
  194. continue;
  195. }
  196. if (currentLineIndex == startLine) {
  197. firstInRange = current;
  198. firstInRangeIndex = i;
  199. i++;
  200. } else {
  201. lineStyles.remove(i);
  202. }
  203. }
  204. int newEndLine = startLine + newLineCount;
  205. if (firstInRange != null) {
  206. int styleIndex = firstInRangeIndex + 1;
  207. for (int lineIndex = firstInRange.lineIndex + 1; lineIndex < newEndLine; lineIndex++) {
  208. LineStyle lineStyle = (LineStyle) firstInRange.clone();
  209. lineStyle.lineIndex = lineIndex;
  210. lineStyle.indent = calcLineIndentCount(document, lineIndex);
  211. lineStyles.add(styleIndex, lineStyle);
  212. styleIndex++;
  213. }
  214. } else {
  215. int styleIndex = firstInRangeIndex;
  216. for (int lineIndex = startLine; lineIndex < newEndLine; lineIndex++) {
  217. int indent = calcLineIndentCount(document, lineIndex);
  218. if (indent > 0) {
  219. LineStyle lineStyle = (LineStyle) RichTextUtils.DEFAULT_LINE_STYLE
  220. .clone();
  221. lineStyle.indent = indent;
  222. lineStyles.add(styleIndex, lineStyle);
  223. styleIndex++;
  224. }
  225. }
  226. }
  227. return firstInRange;
  228. }
  229. public static void updateImagePositions(int start, int oldLength,
  230. int newLength, List<ImagePlaceHolder> images) {
  231. int oldEnd = start + oldLength;
  232. int deltaOffset = newLength - oldLength;
  233. int imagePlaceHolderLength = PLACE_HOLDER.length();
  234. for (int i = 0; i < images.size();) {
  235. ImagePlaceHolder current = images.get(i);
  236. int currentStart = current.offset;
  237. int currentEnd = currentStart + imagePlaceHolderLength;
  238. // before range
  239. if (currentEnd <= start) {
  240. // simply skip
  241. i++;
  242. continue;
  243. }
  244. // after range
  245. if (currentStart >= oldEnd) {
  246. // push back to fit the new range
  247. current.offset += deltaOffset;
  248. // skip
  249. i++;
  250. continue;
  251. }
  252. // remove all images within the old range
  253. images.remove(i);
  254. }
  255. }
  256. /**
  257. * @param start
  258. * --the position of Cursor
  259. * @param oldLength
  260. * --the selection text's length
  261. * @param newLength
  262. * --later input the text's length
  263. * @param hyperlinks
  264. */
  265. public static void updateHyperlinksPositions(int start, int oldLength,
  266. int newLength, List<Hyperlink> hyperlinks) {
  267. int oldEnd = start + oldLength;
  268. int deltaOffset = newLength - oldLength;
  269. for (int i = 0; i < hyperlinks.size();) {
  270. Hyperlink currentHyper = hyperlinks.get(i);
  271. int currentStart = currentHyper.start;
  272. int currentEnd = currentHyper.end();
  273. //in front of range
  274. if (oldEnd <= currentStart) {
  275. currentHyper.start += deltaOffset;
  276. i++;
  277. continue;
  278. }
  279. //behind of range
  280. if (start >= currentEnd) {
  281. i++;
  282. continue;
  283. }
  284. //the overlap at the front half of range
  285. if (oldEnd <= currentEnd && oldEnd > currentStart) {
  286. if (start >= currentStart) {
  287. currentHyper.length += deltaOffset;
  288. if (currentHyper.length == 0) {
  289. hyperlinks.remove(i);
  290. continue;
  291. }
  292. } else {
  293. currentHyper.length = currentHyper.end() - oldEnd;
  294. currentHyper.start = oldEnd + deltaOffset;
  295. }
  296. i++;
  297. continue;
  298. }
  299. // the overlap at the behind half of range
  300. if (start >= currentStart && start < currentEnd) {
  301. if (oldEnd <= currentEnd) {
  302. currentHyper.length += deltaOffset;
  303. if (currentHyper.length == 0) {
  304. hyperlinks.remove(i);
  305. continue;
  306. }
  307. } else {
  308. currentHyper.length = start - currentStart;
  309. }
  310. i++;
  311. continue;
  312. }
  313. hyperlinks.remove(i);
  314. }
  315. }
  316. public static void replaceStyleRanges(int start, int oldLength,
  317. int newLength, List<StyleRange> styles, StyleRange replacement) {
  318. int oldEnd = start + oldLength;
  319. int deltaOffset = newLength - oldLength;
  320. StyleRange last = null;
  321. StyleRange lastStyleBeforeRange = null;
  322. int lastIndexBeforeRange = -1;
  323. for (int styleIndex = 0; styleIndex < styles.size();) {
  324. StyleRange current = styles.get(styleIndex);
  325. int currentStart = current.start;
  326. int currentLength = current.length;
  327. int currentEnd = currentStart + currentLength;
  328. // before the old range
  329. if (currentEnd <= start) {
  330. last = current;
  331. lastStyleBeforeRange = current;
  332. lastIndexBeforeRange = styleIndex;
  333. // simply skip to next style
  334. styleIndex++;
  335. continue;
  336. }
  337. // after the old range
  338. if (currentStart >= oldEnd) {
  339. // push back to fit the new range
  340. current.start += deltaOffset;
  341. // merge with the last style if possible
  342. if (merge(current, last)) {
  343. styles.remove(styleIndex);
  344. } else {
  345. styleIndex++;
  346. }
  347. continue;
  348. }
  349. // some part before the old range
  350. if (currentStart < start) {
  351. // make a copy of that part to protect it from modification
  352. StyleRange beforePart = (StyleRange) current.clone();
  353. beforePart.length = start - currentStart;
  354. styles.add(styleIndex, beforePart);
  355. // refresh the current style range
  356. currentStart = start;
  357. current.start = currentStart;
  358. current.length = currentEnd - currentStart;
  359. last = beforePart;
  360. lastStyleBeforeRange = beforePart;
  361. lastIndexBeforeRange = styleIndex;
  362. styleIndex++;
  363. }
  364. // some part after the old range
  365. if (currentEnd > oldEnd) {
  366. // make a copy of that part to protect it from modification
  367. StyleRange afterPart = (StyleRange) current.clone();
  368. afterPart.start = oldEnd;
  369. afterPart.length = currentEnd - oldEnd;
  370. // refresh the current style range
  371. styles.add(styleIndex + 1, afterPart);
  372. currentEnd = oldEnd;
  373. current.length = currentEnd - currentStart;
  374. }
  375. // remove all style ranges within the old range
  376. styles.remove(styleIndex);
  377. }
  378. StyleRange newStyle = (StyleRange) replacement.clone();
  379. newStyle.start = start;
  380. newStyle.length = newLength;
  381. if (!merge(newStyle, lastStyleBeforeRange)) {
  382. styles.add(lastIndexBeforeRange + 1, newStyle);
  383. }
  384. }
  385. public static boolean modifyTextStyles(int start, int length,
  386. List<StyleRange> styles, IStyleRangeModifier modifier) {
  387. if (length == 0 || modifier == null)
  388. return false;
  389. int end = start + length;
  390. boolean changed = false;
  391. StyleRange last = null;
  392. int unhandledStart = start;
  393. int unhandledEnd = end;
  394. int unhandledIndex = 0;
  395. for (int styleIndex = 0; styleIndex < styles.size();) {
  396. StyleRange current = styles.get(styleIndex);
  397. int currentStart = current.start;
  398. int currentEnd = currentStart + current.length;
  399. // before selection range
  400. if (currentEnd <= start) {
  401. // simply skip to next style
  402. last = current;
  403. styleIndex++;
  404. unhandledIndex = styleIndex;
  405. continue;
  406. }
  407. // after selection range
  408. if (currentStart >= end) {
  409. // merge with the last style if possible
  410. if (merge(current, last)) {
  411. styles.remove(styleIndex);
  412. changed = true;
  413. }
  414. // loop should end as the following style ranges
  415. // are all beyond the selection range and should
  416. // remain unmodified
  417. break;
  418. }
  419. // some part before selection range
  420. if (currentStart < start) {
  421. unhandledStart = currentEnd;
  422. // make a copy of that part to protect it from modification
  423. StyleRange beforePart = (StyleRange) current.clone();
  424. beforePart.length = start - currentStart;
  425. styles.add(styleIndex, beforePart);
  426. changed = true;
  427. last = beforePart;
  428. // refresh the current style range
  429. currentStart = start;
  430. current.start = currentStart;
  431. current.length = currentEnd - currentStart;
  432. styleIndex++;
  433. }
  434. // some part after selection range
  435. if (currentEnd > end) {
  436. unhandledEnd = currentStart;
  437. // make a copy of that part to protect it from modification
  438. StyleRange afterPart = (StyleRange) current.clone();
  439. afterPart.start = end;
  440. afterPart.length = currentEnd - end;
  441. styles.add(styleIndex + 1, afterPart);
  442. changed = true;
  443. // refresh the current style range
  444. currentEnd = end;
  445. current.length = currentEnd - currentStart;
  446. }
  447. // check if there's still unhandled regions before this range
  448. if (currentStart >= unhandledStart) {
  449. // modify and add the unhandled region before this range
  450. if (currentStart > unhandledStart) {
  451. StyleRange newStyle = (StyleRange) RichTextUtils.DEFAULT_STYLE
  452. .clone();
  453. newStyle.start = unhandledStart;
  454. newStyle.length = currentStart - unhandledStart;
  455. modifier.modify(newStyle);
  456. // merge with the last style if possible
  457. if (!merge(newStyle, last)) {
  458. styles.add(styleIndex, newStyle);
  459. last = newStyle;
  460. styleIndex++;
  461. }
  462. changed = true;
  463. }
  464. unhandledStart = currentEnd;
  465. }
  466. // modify current style
  467. changed |= modifier.modify(current);
  468. // merge with the last style if possible
  469. if (merge(current, last)) {
  470. styles.remove(styleIndex);
  471. changed = true;
  472. } else {
  473. last = current;
  474. styleIndex++;
  475. }
  476. unhandledIndex = styleIndex;
  477. }
  478. // check if there's still unhandled regions before this range
  479. if (unhandledEnd > unhandledStart) {
  480. // modify and add the unhandled region before this range
  481. StyleRange newStyle = (StyleRange) RichTextUtils.DEFAULT_STYLE
  482. .clone();
  483. newStyle.start = unhandledStart;
  484. newStyle.length = unhandledEnd - unhandledStart;
  485. modifier.modify(newStyle);
  486. // merge with the last style if possible
  487. if (!merge(newStyle, last)) {
  488. styles.add(unhandledIndex, newStyle);
  489. changed = true;
  490. }
  491. }
  492. return changed;
  493. }
  494. public static boolean merge(StyleRange current, StyleRange last) {
  495. if (current == null)
  496. return false;
  497. if (current.length == 0)
  498. return true;
  499. if (last != null && last.start + last.length == current.start) {
  500. if (isSimilar(current, last)) {
  501. last.length = last.length + current.length;
  502. return true;
  503. }
  504. return false;
  505. }
  506. return isSimilar(current, RichTextUtils.DEFAULT_STYLE);
  507. }
  508. public static boolean modifyLineStyles(int startLine, int lineCount,
  509. List<LineStyle> lineStyles, ILineStyleModifier modifier) {
  510. int endLine = startLine + lineCount;
  511. int unhandledLine = startLine;
  512. int unhandledIndex = 0;
  513. boolean changed = false;
  514. for (int i = 0; i < lineStyles.size();) {
  515. LineStyle current = lineStyles.get(i);
  516. int currentLineIndex = current.lineIndex;
  517. if (currentLineIndex < startLine) {
  518. i++;
  519. unhandledIndex = i;
  520. continue;
  521. }
  522. if (currentLineIndex >= endLine) {
  523. break;
  524. }
  525. if (currentLineIndex > unhandledLine) {
  526. LineStyle lineStyle = new LineStyle(unhandledLine);
  527. boolean modified = modifier.modify(lineStyle);
  528. changed |= modified;
  529. if (modified && !lineStyle.isUnstyled()) {
  530. lineStyles.add(i, lineStyle);
  531. i++;
  532. }
  533. } else {
  534. boolean modified = modifier.modify(current);
  535. changed |= modified;
  536. if (modified && current.isUnstyled()) {
  537. lineStyles.remove(i);
  538. } else {
  539. i++;
  540. }
  541. }
  542. unhandledIndex = i;
  543. unhandledLine++;
  544. }
  545. for (int i = unhandledLine; i < endLine; i++) {
  546. LineStyle lineStyle = new LineStyle(i);
  547. boolean modified = modifier.modify(lineStyle);
  548. changed |= modified;
  549. if (modified && !lineStyle.isUnstyled()) {
  550. lineStyles.add(unhandledIndex, lineStyle);
  551. }
  552. unhandledIndex++;
  553. }
  554. return changed;
  555. }
  556. public static void replaceDocumentIndent(IDocument document, int line,
  557. int newIndent) throws BadLocationException {
  558. IRegion region = document.getLineInformation(line);
  559. int lineOffset = region.getOffset();
  560. int lineLength = region.getLength();
  561. String lineContent = document.get(lineOffset, lineLength);
  562. int oldIndent = calcIndentCount(lineContent);
  563. if (oldIndent != newIndent) {
  564. char[] chars = new char[newIndent];
  565. Arrays.fill(chars, INDENT_CHAR);
  566. String value = String.valueOf(chars);
  567. document.replace(lineOffset, oldIndent, value);
  568. }
  569. }
  570. public static void modifyDocumentIndent(TextViewer viewer,
  571. IDocument document, int line, int deltaIndent)
  572. throws BadLocationException {
  573. if (deltaIndent == 0)
  574. return;
  575. IRegion region = document.getLineInformation(line);
  576. int lineOffset = region.getOffset();
  577. // StyledText styledText = viewer.getTextWidget();
  578. // styledText.setLineBullet(lineOffset, 1, null);
  579. if (deltaIndent > 0) {
  580. char[] chars = new char[deltaIndent];
  581. Arrays.fill(chars, INDENT_CHAR);
  582. String value = String.valueOf(chars);
  583. document.replace(lineOffset, 0, value);
  584. // Bullet bullet = styledText.getLineBullet(lineOffset);
  585. // StyleRange style = new StyleRange();
  586. // style.metrics = new GlyphMetrics(0, 0, 80);
  587. // Bullet bullet = new Bullet(ST.BULLET_NUMBER | ST.BULLET_TEXT, style);
  588. // bullet.text = ".";
  589. // styledText.setLineBullet(lineOffset, 1, bullet);
  590. // document.replace(0, 0, value);
  591. } else if (deltaIndent < 0) {
  592. int lineLength = region.getLength();
  593. String lineContent = document.get(lineOffset, lineLength);
  594. int oldIndent = calcIndentCount(lineContent);
  595. int deleteCount = Math.min(oldIndent, Math.abs(deltaIndent));
  596. if (deleteCount > 0) {
  597. document.replace(lineOffset, deleteCount, EMPTY);
  598. }
  599. }
  600. }
  601. public static int calcLineCount(String text) {
  602. int numDelimiter = 0;
  603. int length = text.length();
  604. for (int i = 0; i < length;) {
  605. if (match(text, i, LineDelimiter)) {
  606. numDelimiter++;
  607. i += LineDelimiter.length();
  608. } else {
  609. i++;
  610. }
  611. }
  612. return numDelimiter + 1;
  613. }
  614. private static boolean match(String source, int start, String target) {
  615. int length = target.length();
  616. if (start + length > source.length())
  617. return false;
  618. for (int i = 0; i < length; i++) {
  619. char c1 = source.charAt(start + i);
  620. char c2 = target.charAt(i);
  621. if (c1 != c2)
  622. return false;
  623. }
  624. return true;
  625. }
  626. public static int calcLineIndentCount(IDocument document, int line) {
  627. try {
  628. IRegion region = document.getLineInformation(line);
  629. int lineOffset = region.getOffset();
  630. int lineLength = region.getLength();
  631. String lineContent = document.get(lineOffset, lineLength);
  632. return calcIndentCount(lineContent);
  633. } catch (BadLocationException e) {
  634. e.printStackTrace();
  635. return 0;
  636. }
  637. }
  638. public static int calcIndentCount(String content) {
  639. int indent = 0;
  640. for (int i = 0; i < content.length(); i++) {
  641. char c = content.charAt(i);
  642. if (c != '\t') {
  643. return indent;
  644. }
  645. indent++;
  646. }
  647. return indent;
  648. }
  649. public static boolean isSimilar(StyleRange sr1, StyleRange sr2) {
  650. if (sr1 == sr2)
  651. return true;
  652. if (sr1 == null || sr2 == null)
  653. return false;
  654. if (!equals(sr1, sr2))
  655. return false;
  656. if (sr1.fontStyle == sr2.fontStyle)
  657. return true;
  658. return false;
  659. }
  660. public static boolean equals(TextStyle style1, TextStyle style2) {
  661. if (style1 == style2)
  662. return true;
  663. if (style1 == null || style2 == null)
  664. return false;
  665. if (style1.foreground != null) {
  666. if (!style1.foreground.equals(style2.foreground))
  667. return false;
  668. } else if (style2.foreground != null)
  669. return false;
  670. if (style1.background != null) {
  671. if (!style1.background.equals(style2.background))
  672. return false;
  673. } else if (style2.background != null)
  674. return false;
  675. if (style1.font != null) {
  676. if (!equals(style1.font, style2.font))
  677. return false;
  678. } else if (style2.font != null)
  679. return false;
  680. if (style1.metrics != null || style2.metrics != null)
  681. return false;
  682. if (style1.underline != style2.underline)
  683. return false;
  684. if (style1.strikeout != style2.strikeout)
  685. return false;
  686. if (style1.rise != style2.rise)
  687. return false;
  688. return true;
  689. }
  690. public static boolean equals(Font f1, Font f2) {
  691. if (f1 == f2)
  692. return true;
  693. if (f1 == null && f2 != null)
  694. return false;
  695. if (f2 == null && f1 != null)
  696. return false;
  697. if (!Util.isMac())
  698. return f1.equals(f2);
  699. if (f1.isDisposed() || f2.isDisposed())
  700. return false;
  701. FontData fd1 = f1.getFontData()[0];
  702. FontData fd2 = f2.getFontData()[0];
  703. return fd1.equals(fd2);
  704. }
  705. // public static List<LineStyle> reduceLineStyles(int startLine,
  706. // List<LineStyle> lineStyles, IRichDocument document) {
  707. // if (lineStyles == null || lineStyles.isEmpty())
  708. // return null;
  709. // LineStyle lineStyle = lineStyles.get(startLine - 1);
  710. // lineStyle.bulletStyle = LineStyle.NONE_STYLE;
  711. // lineStyles.remove(startLine);
  712. // return lineStyles;
  713. // }
  714. public static void replaceHyperlinkHref(IRichDocument doc,
  715. Hyperlink hyperlink, String newHref) {
  716. Hyperlink newHyperlink = (Hyperlink) hyperlink.clone();
  717. newHyperlink.href = newHref;
  718. Hyperlink[] oldHyperlinks = doc.getHyperlinks();
  719. List<Hyperlink> newHyperlinks = new ArrayList<Hyperlink>(
  720. oldHyperlinks.length);
  721. for (Hyperlink oldHyperlink : oldHyperlinks) {
  722. if (oldHyperlink.start == hyperlink.start
  723. && oldHyperlink.length == hyperlink.length) {
  724. newHyperlinks.add(newHyperlink);
  725. } else {
  726. newHyperlinks.add(oldHyperlink);
  727. }
  728. }
  729. doc.setHyperlinks(newHyperlinks.toArray(new Hyperlink[newHyperlinks
  730. .size()]));
  731. }
  732. }