001package com.hfg.xml.msofficexml.xlsx.spreadsheetml.style; 002 003import java.awt.Color; 004import java.awt.Font; 005 006import com.hfg.exception.UnmodifyableObjectException; 007import com.hfg.graphics.ColorUtil; 008import com.hfg.html.attribute.HTMLColor; 009import com.hfg.util.CompareUtil; 010import com.hfg.util.StringBuilderPlus; 011import com.hfg.xml.XMLTag; 012import com.hfg.xml.msofficexml.xlsx.ExcelIndexedColor; 013import com.hfg.xml.msofficexml.xlsx.Xlsx; 014import com.hfg.xml.msofficexml.xlsx.spreadsheetml.SsmlXML; 015import com.hfg.xml.msofficexml.xlsx.spreadsheetml.SsmlXMLTag; 016 017//------------------------------------------------------------------------------ 018/** 019 Represents an Office Open XML spreadsheetml (<ssml:font>) tag. 020 <div> 021 @author J. Alex Taylor, hairyfatguy.com 022 </div> 023 */ 024//------------------------------------------------------------------------------ 025// com.hfg XML/HTML Coding Library 026// 027// This library is free software; you can redistribute it and/or 028// modify it under the terms of the GNU Lesser General Public 029// License as published by the Free Software Foundation; either 030// version 2.1 of the License, or (at your option) any later version. 031// 032// This library is distributed in the hope that it will be useful, 033// but WITHOUT ANY WARRANTY; without even the implied warranty of 034// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 035// Lesser General Public License for more details. 036// 037// You should have received a copy of the GNU Lesser General Public 038// License along with this library; if not, write to the Free Software 039// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 040// 041// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 042// jataylor@hairyfatguy.com 043//------------------------------------------------------------------------------ 044 045public class SsmlFont extends SsmlXMLTag implements Comparable 046{ 047 private Integer mIndex; 048 private XMLTag mSizeTag; 049 private XMLTag mNameTag; 050 private XMLTag mColorTag; 051 private XMLTag mBoldTag; 052 private XMLTag mItalicTag; 053 private XMLTag mShadowTag; 054 private XMLTag mStrikeThroughTag; 055 private XMLTag mTextVertAlignTag; 056 private XMLTag mUnderlineTag; 057 // TODO: Family tag 058 059 protected boolean mLocked; 060 061 //########################################################################## 062 // CONSTRUCTORS 063 //########################################################################## 064 065 //--------------------------------------------------------------------------- 066 public SsmlFont(SsmlXMLTag inSsmlXMLTag) 067 { 068 this(inSsmlXMLTag.getParentDoc()); 069 } 070 071 //--------------------------------------------------------------------------- 072 public SsmlFont(Xlsx inXlsx) 073 { 074 this(inXlsx.getStylesPart()); 075 } 076 077 //--------------------------------------------------------------------------- 078 public SsmlFont(Font inFont, Xlsx inXlsx) 079 { 080 this(inXlsx); 081 setName(inFont.getName()); 082 setSize(inFont.getSize()); 083 if (inFont.isBold()) 084 { 085 setBold(true); 086 } 087 088 if (inFont.isItalic()) 089 { 090 setItalic(true); 091 } 092 } 093 094 //--------------------------------------------------------------------------- 095 public SsmlFont(StylesPart inStylesPart) 096 { 097 super(SsmlXML.FONT, inStylesPart.getParentDoc()); 098 // Register with the styles part 099 mIndex = inStylesPart.defineFont(this); 100 } 101 102 //--------------------------------------------------------------------------- 103 public SsmlFont(Xlsx inXlsx, XMLTag inXMLTag) 104 { 105 super(SsmlXML.FONT, inXlsx); 106 107 XMLTag sizeTag = inXMLTag.getOptionalSubtagByName(SsmlXML.SIZE); 108 if (sizeTag != null) 109 { 110 mSizeTag = sizeTag; 111 } 112 113 XMLTag nameTag = inXMLTag.getOptionalSubtagByName(SsmlXML.NAME); 114 if (nameTag != null) 115 { 116 mNameTag = nameTag; 117 } 118 119 XMLTag colorTag = inXMLTag.getOptionalSubtagByName(SsmlXML.COLOR); 120 if (colorTag != null) 121 { 122 mColorTag = colorTag; 123 } 124 125 XMLTag boldTag = inXMLTag.getOptionalSubtagByName(SsmlXML.BOLD); 126 if (boldTag != null) 127 { 128 mBoldTag = boldTag; 129 } 130 131 XMLTag italicTag = inXMLTag.getOptionalSubtagByName(SsmlXML.ITALIC); 132 if (italicTag != null) 133 { 134 mItalicTag = italicTag; 135 } 136 137 XMLTag shadowTag = inXMLTag.getOptionalSubtagByName(SsmlXML.SHADOW); 138 if (shadowTag != null) 139 { 140 mShadowTag = shadowTag; 141 } 142 143 XMLTag strikeTag = inXMLTag.getOptionalSubtagByName(SsmlXML.STRIKE); 144 if (strikeTag != null) 145 { 146 mStrikeThroughTag = strikeTag; 147 } 148 149 XMLTag textVertTag = inXMLTag.getOptionalSubtagByName(SsmlXML.VERTICAL_ALIGN); 150 if (textVertTag != null) 151 { 152 mTextVertAlignTag = textVertTag; 153 } 154 155 XMLTag underlineTag = inXMLTag.getOptionalSubtagByName(SsmlXML.UNDERLINE); 156 if (underlineTag != null) 157 { 158 mUnderlineTag = underlineTag; 159 } 160 161 } 162 163 164 //########################################################################## 165 // PUBLIC METHODS 166 //########################################################################## 167 168 //--------------------------------------------------------------------------- 169 public String toString() 170 { 171 StringBuilderPlus buffer = new StringBuilderPlus(getName()).setDelimiter("-"); 172 if (isBold()) 173 { 174 buffer.delimitedAppend("BOLD"); 175 if (isItalic()) 176 { 177 buffer.append("ITALIC"); 178 } 179 } 180 else if (isItalic()) 181 { 182 buffer.delimitedAppend("ITALIC"); 183 } 184 else 185 { 186 buffer.delimitedAppend("PLAIN"); 187 } 188 189 buffer.delimitedAppend(getSize()); 190 191 return buffer.toString(); 192 } 193 194 //-------------------------------------------------------------------------- 195 @Override 196 public boolean equals(Object inObj2) 197 { 198 return (0 == compareTo(inObj2)); 199 } 200 201 //-------------------------------------------------------------------------- 202 @Override 203 public int compareTo(Object inObj2) 204 { 205 int result = -1; 206 207 if (inObj2 instanceof SsmlFont) 208 { 209 SsmlFont font2 = (SsmlFont) inObj2; 210 211 result = CompareUtil.compare(getName(), font2.getName()); 212 213 if (0 == result) 214 { 215 result = CompareUtil.compare(getSize(), font2.getSize()); 216 217 if (0 == result) 218 { 219 result = CompareUtil.compare(getColor(), font2.getColor()); 220 221 if (0 == result) 222 { 223 result = CompareUtil.compare(isBold(), font2.isBold()); 224 225 if (0 == result) 226 { 227 result = CompareUtil.compare(isItalic(), font2.isItalic()); 228 229 if (0 == result) 230 { 231 result = CompareUtil.compare(hasShadow(), font2.hasShadow()); 232 233 if (0 == result) 234 { 235 result = CompareUtil.compare(hasStrikeThrough(), font2.hasStrikeThrough()); 236 237 if (0 == result) 238 { 239 result = CompareUtil.compare(getTextVerticalAlignment(), font2.getTextVerticalAlignment()); 240 241 if (0 == result) 242 { 243 result = CompareUtil.compare(getUnderline(), font2.getUnderline()); 244 } 245 } 246 } 247 } 248 } 249 } 250 } 251 } 252 } 253 254 return result; 255 } 256 257 //-------------------------------------------------------------------------- 258 public boolean isLocked() 259 { 260 return mLocked; 261 } 262 263 //-------------------------------------------------------------------------- 264 public SsmlFont lock() 265 { 266 mLocked = true; 267 return this; 268 } 269 270 //--------------------------------------------------------------------------- 271 @Override 272 public SsmlFont clone() 273 { 274 SsmlFont clone = (SsmlFont) super.clone(); 275 276 // The clone should be unlocked (modifiable) 277 clone.mLocked = false; 278 279 // These cached values will be repopulated if needed 280 clone.clearSubtags(); 281 clone.mNameTag = null; 282 clone.mSizeTag = null; 283 clone.mColorTag = null; 284 clone.mBoldTag = null; 285 clone.mItalicTag = null; 286 clone.mShadowTag = null; 287 clone.mUnderlineTag = null; 288 clone.mTextVertAlignTag = null; 289 290 if (getName() != null) 291 { 292 clone.setName(getName()); 293 } 294 295 if (mSizeTag != null) 296 { 297 clone.setSize(getSize()); 298 } 299 300 if (getColor() != null) 301 { 302 clone.setColor(getColor()); 303 } 304 305 if (isBold()) 306 { 307 clone.setBold(true); 308 } 309 310 if (isItalic()) 311 { 312 clone.setItalic(true); 313 } 314 315 if (hasShadow()) 316 { 317 clone.setShadow(true); 318 } 319 320 if (hasStrikeThrough()) 321 { 322 clone.setStrikeThrough(true); 323 } 324 325 if (getUnderline() != null) 326 { 327 clone.setUnderline(getUnderline()); 328 } 329 330 if (getTextVerticalAlignment() != null) 331 { 332 clone.setTextVerticalAlignment(getTextVerticalAlignment()); 333 } 334 335 // Register with the styles part 336 clone.mIndex = getParentDoc().getStylesPart().defineFont(clone); 337 338 return clone; 339 } 340 341 //--------------------------------------------------------------------------- 342 public Font toFont() 343 { 344 int style = (mBoldTag != null ? Font.BOLD : 0) + (mItalicTag != null ? Font.ITALIC : 0); 345 346 return new Font(getName(), style, getSize()); 347 } 348 349 //--------------------------------------------------------------------------- 350 /** 351 Only for use by the StylesPart when setting a new value for the default font. 352 * @param inValue the new index value 353 * @return this object to enable chaining 354 */ 355 protected SsmlFont setIndex(Integer inValue) 356 { 357 mIndex = inValue; 358 return this; 359 } 360 361 //--------------------------------------------------------------------------- 362 public Integer getIndex() 363 { 364 return mIndex; 365 } 366 367 //--------------------------------------------------------------------------- 368 public SsmlFont setSize(int inValue) 369 { 370 checkLock(); 371 372 if (null == mSizeTag) 373 { 374 // Check it it has been added via addSubtag()... 375 mSizeTag = getOptionalSubtagByName(SsmlXML.SIZE); 376 if (null == mSizeTag) 377 { 378 mSizeTag = new XMLTag(SsmlXML.SIZE); 379 addSubtag(mSizeTag); 380 } 381 } 382 383 mSizeTag.setAttribute(SsmlXML.VALUE_ATT, inValue); 384 385 return this; 386 } 387 388 //--------------------------------------------------------------------------- 389 public int getSize() 390 { 391 return (mSizeTag != null ? Integer.parseInt(mSizeTag.getAttributeValue(SsmlXML.VALUE_ATT)) : 0); 392 } 393 394 //--------------------------------------------------------------------------- 395 public boolean isBold() 396 { 397 return mBoldTag != null; 398 } 399 400 //--------------------------------------------------------------------------- 401 public SsmlFont setBold(boolean inValue) 402 { 403 checkLock(); 404 405 if (null == mBoldTag) 406 { 407 // Check if it has been added via addSubtag()... 408 mBoldTag = getOptionalSubtagByName(SsmlXML.BOLD); 409 } 410 411 if (inValue) 412 { 413 if (null == mBoldTag) 414 { 415 mBoldTag = new XMLTag(SsmlXML.BOLD); 416 addSubtag(mBoldTag); 417 } 418 } 419 else if (mBoldTag != null) 420 { 421 removeSubtag(mBoldTag); 422 mBoldTag = null; 423 } 424 425 return this; 426 } 427 428 //--------------------------------------------------------------------------- 429 public boolean isItalic() 430 { 431 return mItalicTag != null; 432 } 433 434 //--------------------------------------------------------------------------- 435 public SsmlFont setItalic(boolean inValue) 436 { 437 checkLock(); 438 439 if (null == mItalicTag) 440 { 441 // Check it it has been added via addSubtag()... 442 mItalicTag = getOptionalSubtagByName(SsmlXML.ITALIC); 443 } 444 445 if (inValue) 446 { 447 if (null == mItalicTag) 448 { 449 mItalicTag = new XMLTag(SsmlXML.ITALIC); 450 addSubtag(mItalicTag); 451 } 452 } 453 else if (mItalicTag != null) 454 { 455 removeSubtag(mItalicTag); 456 mItalicTag = null; 457 } 458 459 return this; 460 } 461 462 463 //--------------------------------------------------------------------------- 464 public boolean hasStrikeThrough() 465 { 466 if (null == mStrikeThroughTag) 467 { 468 // Check if it has been added via addSubtag()... 469 mStrikeThroughTag = getOptionalSubtagByName(SsmlXML.STRIKE); 470 } 471 472 return (mStrikeThroughTag != null); 473 } 474 475 //--------------------------------------------------------------------------- 476 public SsmlFont setStrikeThrough(boolean inValue) 477 { 478 checkLock(); 479 480 if (null == mStrikeThroughTag) 481 { 482 // Check it it has been added via addSubtag()... 483 mStrikeThroughTag = getOptionalSubtagByName(SsmlXML.STRIKE); 484 } 485 486 if (inValue) 487 { 488 if (null == mStrikeThroughTag) 489 { 490 mStrikeThroughTag = new XMLTag(SsmlXML.STRIKE); 491 addSubtag(mStrikeThroughTag); 492 } 493 } 494 else if (mStrikeThroughTag != null) 495 { 496 removeSubtag(mStrikeThroughTag); 497 mStrikeThroughTag = null; 498 } 499 500 return this; 501 } 502 503 504 //--------------------------------------------------------------------------- 505 public boolean hasShadow() 506 { 507 if (null == mShadowTag) 508 { 509 // Check if it has been added via addSubtag()... 510 mShadowTag = getOptionalSubtagByName(SsmlXML.SHADOW); 511 } 512 513 return (mShadowTag != null); 514 } 515 516 //--------------------------------------------------------------------------- 517 public SsmlFont setShadow(boolean inValue) 518 { 519 checkLock(); 520 521 if (null == mShadowTag) 522 { 523 // Check if it has been added via addSubtag()... 524 mShadowTag = getOptionalSubtagByName(SsmlXML.SHADOW); 525 } 526 527 if (inValue) 528 { 529 if (null == mShadowTag) 530 { 531 mShadowTag = new XMLTag(SsmlXML.SHADOW); 532 addSubtag(mShadowTag); 533 } 534 } 535 else if (mShadowTag != null) 536 { 537 removeSubtag(mShadowTag); 538 mShadowTag = null; 539 } 540 541 return this; 542 } 543 544 545 //--------------------------------------------------------------------------- 546 public SsmlUnderlineType getUnderline() 547 { 548 if (null == mUnderlineTag) 549 { 550 // Check if it has been added via addSubtag()... 551 mUnderlineTag = getOptionalSubtagByName(SsmlXML.UNDERLINE); 552 } 553 554 return (mUnderlineTag != null ? SsmlUnderlineType.valueOf(mUnderlineTag.getAttributeValue(SsmlXML.VALUE_ATT)) : null); 555 } 556 557 //--------------------------------------------------------------------------- 558 public SsmlFont setUnderline(SsmlUnderlineType inValue) 559 { 560 checkLock(); 561 562 if (null == mUnderlineTag) 563 { 564 // Check if it has been added via addSubtag()... 565 mUnderlineTag = getOptionalSubtagByName(SsmlXML.UNDERLINE); 566 } 567 568 if (inValue != null) 569 { 570 if (null == mUnderlineTag) 571 { 572 mUnderlineTag = new XMLTag(SsmlXML.UNDERLINE); 573 addSubtag(mUnderlineTag); 574 } 575 576 mUnderlineTag.setAttribute(SsmlXML.VALUE_ATT, inValue.name()); 577 } 578 else if (mUnderlineTag != null) 579 { 580 removeSubtag(mUnderlineTag); 581 mUnderlineTag = null; 582 } 583 584 return this; 585 } 586 587 //--------------------------------------------------------------------------- 588 public SsmlFont setTextVerticalAlignment(SsmlTextVerticalAlignRunType inValue) 589 { 590 checkLock(); 591 592 if (null == mTextVertAlignTag) 593 { 594 // Check it it has been added via addSubtag()... 595 mTextVertAlignTag = getOptionalSubtagByName(SsmlXML.VERTICAL_ALIGN); 596 } 597 598 if (inValue != null) 599 { 600 if (null == mTextVertAlignTag) 601 { 602 mTextVertAlignTag = new XMLTag(SsmlXML.VERTICAL_ALIGN); 603 addSubtag(mTextVertAlignTag); 604 } 605 606 mTextVertAlignTag.setAttribute(SsmlXML.VALUE_ATT, inValue.name()); 607 } 608 else if (mTextVertAlignTag != null) 609 { 610 removeSubtag(mTextVertAlignTag); 611 mTextVertAlignTag = null; 612 } 613 614 return this; 615 } 616 617 //--------------------------------------------------------------------------- 618 public SsmlTextVerticalAlignRunType getTextVerticalAlignment() 619 { 620 SsmlTextVerticalAlignRunType value = null; 621 622 if (null == mTextVertAlignTag) 623 { 624 // Check if it has been added via addSubtag()... 625 mTextVertAlignTag = getOptionalSubtagByName(SsmlXML.VERTICAL_ALIGN); 626 } 627 628 if (mTextVertAlignTag != null) 629 { 630 value = SsmlTextVerticalAlignRunType.valueOf(mTextVertAlignTag.getAttributeValue(SsmlXML.VALUE_ATT)); 631 } 632 633 return value; 634 } 635 636 //--------------------------------------------------------------------------- 637 public SsmlFont setColor(Color inValue) 638 { 639 checkLock(); 640 641 if (null == mColorTag) 642 { 643 // Check if it has been added via addSubtag()... 644 mColorTag = getOptionalSubtagByName(SsmlXML.COLOR); 645 } 646 647 if (inValue != null) 648 { 649 if (null == mColorTag) 650 { 651 mColorTag = new XMLTag(SsmlXML.COLOR); 652 addSubtag(mColorTag); 653 } 654 655 if (inValue instanceof ExcelIndexedColor) 656 { 657 mColorTag.setAttribute(SsmlXML.INDEXED_ATT, ((ExcelIndexedColor)inValue).getIndex()); 658 } 659 else 660 { 661 mColorTag.setAttribute(SsmlXML.RGB_ATT, ColorUtil.colorToHex(inValue)); 662 } 663 } 664 else if (mColorTag != null) 665 { 666 removeSubtag(mColorTag); 667 mColorTag = null; 668 } 669 670 return this; 671 } 672 673 //--------------------------------------------------------------------------- 674 public Color getColor() 675 { 676 Color value = null; 677 678 if (null == mColorTag) 679 { 680 // Check if it has been added via addSubtag()... 681 mColorTag = getOptionalSubtagByName(SsmlXML.COLOR); 682 } 683 684 if (mColorTag != null) 685 { 686 if (mColorTag.hasAttribute(SsmlXML.RGB_ATT)) 687 { 688 value = HTMLColor.valueOf("#" + mColorTag.getAttributeValue(SsmlXML.RGB_ATT)); 689 } 690 else if (mColorTag.hasAttribute(SsmlXML.INDEXED_ATT)) 691 { 692 value = ExcelIndexedColor.valueOf(Integer.parseInt(mColorTag.getAttributeValue(SsmlXML.INDEXED_ATT))); 693 } 694 } 695 696 return value; 697 } 698 699 700 //--------------------------------------------------------------------------- 701 public SsmlFont setName(String inValue) 702 { 703 checkLock(); 704 705 if (null == mNameTag) 706 { 707 // Check if it has been added via addSubtag()... 708 mNameTag = getOptionalSubtagByName(SsmlXML.NAME); 709 if (null == mNameTag) 710 { 711 mNameTag = new XMLTag(SsmlXML.NAME); 712 addSubtag(mNameTag); 713 } 714 } 715 716 mNameTag.setAttribute(SsmlXML.VALUE_ATT, inValue); 717 718 return this; 719 } 720 721 //--------------------------------------------------------------------------- 722 public String getName() 723 { 724 return (mNameTag != null ? mNameTag.getAttributeValue(SsmlXML.VALUE_ATT) : null); 725 } 726 727 //########################################################################## 728 // PRIVATE METHODS 729 //########################################################################## 730 731 //--------------------------------------------------------------------------- 732 private void checkLock() 733 { 734 if (isLocked()) 735 { 736 throw new UnmodifyableObjectException("This " + getClass().getSimpleName() + " object is locked and cannot be modified!"); 737 } 738 } 739}