Annotation of modules/damieng/graphical_editor/daxe/lib/src/toolbar.dart, revision 1.1

1.1     ! damieng     1: /*
        !             2:   This file is part of Daxe.
        !             3: 
        !             4:   Daxe is free software: you can redistribute it and/or modify
        !             5:   it under the terms of the GNU General Public License as published by
        !             6:   the Free Software Foundation, either version 3 of the License, or
        !             7:   (at your option) any later version.
        !             8: 
        !             9:   Daxe is distributed in the hope that it will be useful,
        !            10:   but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            12:   GNU General Public License for more details.
        !            13: 
        !            14:   You should have received a copy of the GNU General Public License
        !            15:   along with Daxe.  If not, see <http://www.gnu.org/licenses/>.
        !            16: */
        !            17: 
        !            18: part of daxe;
        !            19: 
        !            20: class Toolbar {
        !            21:   List<ToolbarItem> items;
        !            22:   List<x.Element> cacheRefs = null;
        !            23:   static final String iconPath = 'packages/daxe/images/toolbar/';
        !            24:   
        !            25:   Toolbar([Config cfg]) {
        !            26:     items = new List<ToolbarItem>();
        !            27:     if (doc.saveURL != null) {
        !            28:       ToolbarBox documentBox = new ToolbarBox();
        !            29:       documentBox.add(new ToolbarButton(Strings.get('menu.save'), iconPath + 'document_save.png',
        !            30:           () => page.save(), null));
        !            31:       items.add(documentBox);
        !            32:     }
        !            33:     ToolbarBox historyBox = new ToolbarBox();
        !            34:     historyBox.add(new ToolbarButton(Strings.get('undo.undo'), iconPath + 'history_undo.png',
        !            35:         () => doc.undo(), null, data:"undo", enabled:false));
        !            36:     historyBox.add(new ToolbarButton(Strings.get('undo.redo'), iconPath + 'history_redo.png',
        !            37:         () => doc.redo(), null, data:"redo", enabled:false));
        !            38:     items.add(historyBox);
        !            39:     ToolbarBox findBox = new ToolbarBox();
        !            40:     findBox.add(new ToolbarButton(Strings.get('find.find_replace'), iconPath + 'find.png',
        !            41:         () => (new FindDialog()).show(), null));
        !            42:     items.add(findBox);
        !            43:     if (cfg != null) {
        !            44:       // Buttons to insert new elements
        !            45:       ToolbarBox insertBox = new ToolbarBox();
        !            46:       List<x.Element> refs = cfg.elementsWithType('fichier');
        !            47:       if (refs != null && refs.length > 0) {
        !            48:         addInsertButton(cfg, insertBox, refs, iconPath + 'insert_image.png');
        !            49:       }
        !            50:       refs = cfg.elementsWithType('equationmem');
        !            51:       if (refs != null && refs.length > 0) {
        !            52:         addInsertButton(cfg, insertBox, refs, iconPath + 'equation.png');
        !            53:       }
        !            54:       refs = cfg.elementsWithType('symbole2');
        !            55:       if (refs != null && refs.length > 0) {
        !            56:         addInsertButton(cfg, insertBox, refs, iconPath + 'insert_symbol.png');
        !            57:       }
        !            58:       refs = cfg.elementsWithType('tabletexte');
        !            59:       if (refs != null && refs.length > 0) {
        !            60:         addInsertButton(cfg, insertBox, refs, iconPath + 'insert_table.png');
        !            61:       }
        !            62:       refs = cfg.elementsWithType('liste');
        !            63:       if (refs != null && refs.length > 0) {
        !            64:         addInsertButton(cfg, insertBox, refs, iconPath + 'ul.png');
        !            65:       }
        !            66:       items.add(insertBox);
        !            67:       // List buttons
        !            68:       List<x.Element> ulRefs = DNWList.ulRefs();
        !            69:       List<x.Element> olRefs = DNWList.olRefs();
        !            70:       if (ulRefs.length > 0 || olRefs.length > 0) {
        !            71:         ToolbarBox listBox = new ToolbarBox();
        !            72:         if (ulRefs.length > 0) {
        !            73:           ToolbarButton button = new ToolbarButton(_documentationFor(ulRefs[0]), iconPath + 'ul.png',
        !            74:               null, listButtonUpdate, data:new ToolbarStyleInfo(ulRefs, null, null));
        !            75:           button.action = () {
        !            76:             if (button.selected)
        !            77:               DNWList.riseLevel();
        !            78:             else
        !            79:               DNWList.addList((button.data as ToolbarStyleInfo).validRef);
        !            80:           };
        !            81:           listBox.add(button);
        !            82:         }
        !            83:         if (olRefs.length > 0) {
        !            84:           ToolbarButton button = new ToolbarButton(_documentationFor(olRefs[0]), iconPath + 'ol.png',
        !            85:               null, listButtonUpdate, data:new ToolbarStyleInfo(olRefs, null, null));
        !            86:           button.action = () {
        !            87:             if (button.selected)
        !            88:               DNWList.riseLevel();
        !            89:             else
        !            90:               DNWList.addList((button.data as ToolbarStyleInfo).validRef);
        !            91:           };
        !            92:           listBox.add(button);
        !            93:         }
        !            94:         listBox.add(new ToolbarButton(Strings.get('toolbar.rise_list_level'), iconPath + 'list_rise_level.png',
        !            95:             () => DNWList.riseLevel(), riseListLevelButtonUpdate, data:'rise_list_level'));
        !            96:         bool possibleListInItem = true; // will be true if it is always possible to have a list in an item of the same type
        !            97:         for (x.Element ulRef in ulRefs)
        !            98:           if (doc.cfg.findSubElement(DNWList.findItemRef(ulRef), ulRefs) == null)
        !            99:             possibleListInItem = false;
        !           100:         for (x.Element olRef in olRefs)
        !           101:           if (doc.cfg.findSubElement(DNWList.findItemRef(olRef), olRefs) == null)
        !           102:             possibleListInItem = false;
        !           103:         if (possibleListInItem)
        !           104:           listBox.add(new ToolbarButton(Strings.get('toolbar.lower_list_level'), iconPath + 'list_lower_level.png',
        !           105:               () => DNWList.lowerLevel(), lowerListLevelButtonUpdate, data:'lower_list_level'));
        !           106:         items.add(listBox);
        !           107:       }
        !           108:       // Link/Anchor buttons
        !           109:       List<x.Element> aRefs = DNAnchor.aRefs();
        !           110:       if (aRefs != null && aRefs.length > 0) {
        !           111:         ToolbarBox anchorBox = new ToolbarBox();
        !           112:         ToolbarButton button = new ToolbarButton(Strings.get('toolbar.insert_link'),
        !           113:             iconPath + 'add_link.png',
        !           114:             null, insertLinkButtonUpdate,
        !           115:             data:new ToolbarStyleInfo(aRefs, null, null));
        !           116:         button.action = () => DNAnchor.addLink((button.data as ToolbarStyleInfo).validRef);
        !           117:         anchorBox.add(button);
        !           118:         button = new ToolbarButton(Strings.get('toolbar.remove_link'),
        !           119:             iconPath + 'remove_link.png',
        !           120:             () => DNAnchor.removeLink(), removeLinkButtonUpdate, 
        !           121:             data:new ToolbarStyleInfo(aRefs, null, null));
        !           122:         anchorBox.add(button);
        !           123:         button = new ToolbarButton(Strings.get('toolbar.insert_anchor'),
        !           124:             iconPath + 'anchor.png',
        !           125:             null, insertButtonUpdate,
        !           126:             data:new ToolbarStyleInfo(aRefs, null, null));
        !           127:         button.action = () => DNAnchor.addAnchor((button.data as ToolbarStyleInfo).validRef);
        !           128:         anchorBox.add(button);
        !           129:         items.add(anchorBox);
        !           130:       }
        !           131:       // Style buttons
        !           132:       ToolbarBox styleBox = new ToolbarBox();
        !           133:       List<x.Element> all = cfg.allElementsList();
        !           134:       for (x.Element ref in all) {
        !           135:         String dtype = cfg.elementDisplayType(ref);
        !           136:         if (dtype == 'style') {
        !           137:           String style = cfg.elementParameterValue(ref, 'style', null);
        !           138:           if (style == 'GRAS') {
        !           139:             addStyleButton(cfg, styleBox, ref, iconPath + 'style_bold.png', 'B');
        !           140:           } else if (style == 'ITALIQUE') {
        !           141:             addStyleButton(cfg, styleBox, ref, iconPath + 'style_italic.png', 'I');
        !           142:           } else if (style == 'EXPOSANT') {
        !           143:             addStyleButton(cfg, styleBox, ref, iconPath + 'style_superscript.png');
        !           144:           } else if (style == 'INDICE') {
        !           145:             addStyleButton(cfg, styleBox, ref, iconPath + 'style_subscript.png');
        !           146:           } else if (style == 'BARRE') {
        !           147:             addStyleButton(cfg, styleBox, ref, iconPath + 'style_strikethrough.png');
        !           148:           } else if (style == 'SOULIGNE') {
        !           149:             addStyleButton(cfg, styleBox, ref, iconPath + 'style_underline.png');
        !           150:           }
        !           151:         }
        !           152:       }
        !           153:       if (styleBox.length > 0) {
        !           154:         styleBox.add(new ToolbarButton(Strings.get('toolbar.remove_styles'), iconPath + 'remove_styles.png',
        !           155:             () => DNStyle.removeStylesFromSelection(), null, data:"remove_styles"));
        !           156:         items.add(styleBox);
        !           157:       }
        !           158:       if (doc.hiddenParaRefs != null) {
        !           159:         // Align buttons
        !           160:         String pStyleAtt = doc.cfg.elementParameterValue(doc.hiddenParaRefs[0], 'styleAtt', 'style');
        !           161:         // check if style attribute is allowed for hidden paragraphs
        !           162:         List<x.Element> attRefs = doc.cfg.elementAttributes(doc.hiddenParaRefs[0]);
        !           163:         bool found = false;
        !           164:         for (x.Element attRef in attRefs) {
        !           165:           if (doc.cfg.attributeName(attRef) == pStyleAtt) {
        !           166:             found = true;
        !           167:             break;
        !           168:           }
        !           169:         }
        !           170:         if (found) {
        !           171:           ToolbarBox alignBox = new ToolbarBox();
        !           172:           addParagraphCssButton(alignBox, 'text-align', 'left',
        !           173:               Strings.get('toolbar.align_left'), iconPath + 'align_left.png');
        !           174:           addParagraphCssButton(alignBox, 'text-align', 'right',
        !           175:               Strings.get('toolbar.align_right'), iconPath + 'align_right.png');
        !           176:           addParagraphCssButton(alignBox, 'text-align', 'center',
        !           177:               Strings.get('toolbar.align_center'), iconPath + 'align_center.png');
        !           178:           addParagraphCssButton(alignBox, 'text-align', 'justify',
        !           179:               Strings.get('toolbar.align_justify'), iconPath + 'align_justify.png');
        !           180:           items.add(alignBox);
        !           181:         }
        !           182:       }
        !           183:       x.Element spanRef = DNStyleSpan.styleSpanRef();
        !           184:       if (spanRef != null) {
        !           185:         // Font menu
        !           186:         List<String> fonts = ['serif', 'sans-serif', 'cursive', 'fantasy', 'monospace'];
        !           187:         ToolbarMenu tbmenu = _makeStyleToolbarMenu(Strings.get('toolbar.font'), "font-family", fonts);
        !           188:         items.add(tbmenu);
        !           189:         /*
        !           190:         A size menu is a bad idea: larger font sizes are used for titles and it is
        !           191:         important to be able to extract titles automatically
        !           192:         
        !           193:         // Size menu
        !           194:         List<String> sizes = ['8', '9', '10', '11', '12', '14', '16', '18',
        !           195:                               '20', '24', '28', '32', '36', '48', '72'];
        !           196:         tbmenu = _makeStyleToolbarMenu(Strings.get('toolbar.size'), "font-size", sizes, "px");
        !           197:         items.add(tbmenu);
        !           198:         */
        !           199:       }
        !           200:     }
        !           201:   }
        !           202:   
        !           203:   ToolbarMenu _makeStyleToolbarMenu(String title, String cssName, List<String> cssValues,
        !           204:                                     [String cssUnit]) {
        !           205:     Menu menu = new Menu(title);
        !           206:     menu.parent = this;
        !           207:     x.Element styleRef = DNStyleSpan.styleSpanRef();
        !           208:     for (String cssValue in cssValues) {
        !           209:       String cssValueWithUnit = cssValue;
        !           210:       if (cssUnit != null)
        !           211:         cssValueWithUnit += cssUnit;
        !           212:       MenuItem menuItem = new MenuItem(cssValue, null,
        !           213:           data:new ToolbarStyleInfo([styleRef], cssName, cssValueWithUnit));
        !           214:       menuItem.action = () {
        !           215:         if (menuItem.checked) {
        !           216:           Position start = page.getSelectionStart();
        !           217:           Position end = page.getSelectionEnd();
        !           218:           if (start == end && start.dn is DNText && start.dn.parent.ref == styleRef &&
        !           219:               (start.dn.parent as DNStyle).matchesCss(cssName, cssValueWithUnit) &&
        !           220:               start.dnOffset == start.dn.offsetLength && start.dn.nextSibling == null) {
        !           221:             // we are at the end of the style
        !           222:             // just move the cursor position outside of the style
        !           223:             DaxeNode styleNode = start.dn.parent;
        !           224:             page.moveCursorTo(new Position(styleNode.parent, styleNode.parent.offsetOf(styleNode)+1));
        !           225:             page.updateAfterPathChange();
        !           226:           } else
        !           227:             DNStyle.removeStylesFromSelection(styleRef, cssName);
        !           228:         } else {
        !           229:           DNStyle.removeAndApplyStyleToSelection(styleRef, cssName, cssValueWithUnit);
        !           230:         }
        !           231:       };
        !           232:       menu.add(menuItem);
        !           233:     }
        !           234:     ToolbarMenu tbmenu = new ToolbarMenu(menu, styleMenuUpdate, this);
        !           235:     return(tbmenu);
        !           236:   }
        !           237:   
        !           238:   add(ToolbarItem item) {
        !           239:     items.add(item);
        !           240:   }
        !           241:   
        !           242:   insert(ToolbarItem item, int position) {
        !           243:     items.insert(position, item);
        !           244:   }
        !           245:   
        !           246:   remove(int position) {
        !           247:     items.remove(position);
        !           248:   }
        !           249:   
        !           250:   List<ToolbarButton> get buttons {
        !           251:     List<ToolbarButton> buttons = new List<ToolbarButton>();
        !           252:     for (ToolbarItem item in items) {
        !           253:       if (item is ToolbarBox)
        !           254:         buttons.addAll(item.buttons);
        !           255:     }
        !           256:     return(buttons);
        !           257:   }
        !           258:   
        !           259:   /**
        !           260:    * Returns a list of all element references used in the toolbar.
        !           261:    */
        !           262:   List<x.Element> elementRefs() {
        !           263:     if (cacheRefs != null)
        !           264:       return(cacheRefs);
        !           265:     List<x.Element> list = new List<x.Element>();
        !           266:     for (ToolbarItem item in items) {
        !           267:       if (item is ToolbarBox) {
        !           268:         for (ToolbarButton button in item.buttons) {
        !           269:           if (button.data is ToolbarStyleInfo) {
        !           270:             ToolbarStyleInfo info = button.data;
        !           271:             if (info.possibleRefs != null)
        !           272:               list.addAll(info.possibleRefs);
        !           273:           }
        !           274:         }
        !           275:       } else if (item is ToolbarMenu) {
        !           276:         Menu menu = item.menu;
        !           277:         for (MenuItem menuItem in menu.items) {
        !           278:           if (menuItem.data is ToolbarStyleInfo) {
        !           279:             ToolbarStyleInfo info = menuItem.data;
        !           280:             if (info.possibleRefs != null)
        !           281:               list.addAll(info.possibleRefs);
        !           282:           }
        !           283:         }
        !           284:       }
        !           285:     }
        !           286:     cacheRefs = list;
        !           287:     return(list);
        !           288:   }
        !           289:   
        !           290:   h.Element html() {
        !           291:     h.DivElement div = new h.DivElement();
        !           292:     div.classes.add('toolbar');
        !           293:     for (ToolbarItem item in items) {
        !           294:       div.append(item.html());
        !           295:     }
        !           296:     return(div);
        !           297:   }
        !           298:   
        !           299:   String _documentationFor(x.Element ref) {
        !           300:     String documentation = doc.cfg.documentation(ref);
        !           301:     if (documentation == null)
        !           302:       documentation = doc.cfg.elementTitle(ref);
        !           303:     return(documentation);
        !           304:   }
        !           305:   
        !           306:   addInsertButton(Config cfg, ToolbarBox box, List<x.Element> refs, String icon) {
        !           307:     ToolbarButton button = new ToolbarButton(_documentationFor(refs[0]), icon,
        !           308:         null, insertButtonUpdate,
        !           309:         data:new ToolbarStyleInfo(refs, null, null));
        !           310:     button.action = () => doc.insertNewNode((button.data as ToolbarStyleInfo).validRef, 'element');
        !           311:     box.add(button);
        !           312:   }
        !           313:   
        !           314:   static void insertButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           315:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           316:     // element insert
        !           317:     ToolbarStyleInfo info = button.data;
        !           318:     List<x.Element> refs = info.possibleRefs;
        !           319:     if (info.findValidRef(validRefs))
        !           320:       button.enable();
        !           321:     else
        !           322:       button.disable();
        !           323:   }
        !           324:   
        !           325:   addStyleButton(Config cfg, ToolbarBox box, x.Element ref, String icon, [String shortcut=null]) {
        !           326:     ToolbarButton button = new ToolbarButton(_documentationFor(ref), icon, null, dnStyleButtonUpdate,
        !           327:         data:new ToolbarStyleInfo([ref], null, null), shortcut:shortcut);
        !           328:     button.action = () {
        !           329:       if (button.selected) {
        !           330:         Position start = page.getSelectionStart();
        !           331:         Position end = page.getSelectionEnd();
        !           332:         if (start == end && start.dn is DNText && start.dn.parent.ref == ref &&
        !           333:             start.dnOffset == start.dn.offsetLength && start.dn.nextSibling == null) {
        !           334:           // we are at the end of the style
        !           335:           // just move the cursor position outside of the style
        !           336:           DaxeNode styleNode = start.dn.parent;
        !           337:           page.moveCursorTo(new Position(styleNode.parent, styleNode.parent.offsetOf(styleNode)+1));
        !           338:           page.updateAfterPathChange();
        !           339:         } else
        !           340:           DNStyle.removeStylesFromSelection(ref);
        !           341:       } else {
        !           342:         DNStyle.applyStyleInsideSelection(ref);
        !           343:       }
        !           344:     };
        !           345:     box.add(button);
        !           346:   }
        !           347:   
        !           348:   static void dnStyleButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           349:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           350:     // DNStyle, style with no css (as with the b element)
        !           351:     ToolbarStyleInfo info = button.data;
        !           352:     List<x.Element> refs = info.possibleRefs;
        !           353:     bool foundAncestor = false;
        !           354:     for (x.Element possibleRef in refs) {
        !           355:       if (ancestorRefs.contains(possibleRef)) {
        !           356:         foundAncestor = true;
        !           357:         break;
        !           358:       }
        !           359:     }
        !           360:     if (foundAncestor) {
        !           361:       button.enable();
        !           362:       button.select();
        !           363:     } else {
        !           364:       if (selectedNode != null && refs.contains(selectedNode.ref))
        !           365:         button.select();
        !           366:       else
        !           367:         button.deselect();
        !           368:       if (info.findValidRef(validRefs))
        !           369:         button.enable();
        !           370:       else
        !           371:         button.disable();
        !           372:     }
        !           373:   }
        !           374:   
        !           375:   static void styleSpanButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           376:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           377:     // DNSpanStyle, span style
        !           378:     ToolbarStyleInfo info = button.data;
        !           379:     x.Element ref = info.possibleRefs[0];
        !           380:     bool foundAncestor = false;
        !           381:     for (DaxeNode n = parent; n != null; n = n.parent) {
        !           382:       if (n.ref == ref && (n as DNStyleSpan).matchesCss(info.cssName, info.cssValue)) {
        !           383:         foundAncestor = true;
        !           384:         break;
        !           385:       }
        !           386:     }
        !           387:     if (foundAncestor) {
        !           388:       button.enable();
        !           389:       button.select();
        !           390:     } else {
        !           391:       if (selectedNode != null && ref == selectedNode.ref &&
        !           392:           (selectedNode as DNStyleSpan).matchesCss(info.cssName, info.cssValue)) {
        !           393:         button.select();
        !           394:       } else {
        !           395:         button.deselect();
        !           396:       }
        !           397:       if (validRefs.contains(ref))
        !           398:         button.enable();
        !           399:       else
        !           400:         button.disable();
        !           401:     }
        !           402:   }
        !           403:   
        !           404:   addParagraphCssButton(ToolbarBox alignBox, String cssName, String cssValue,
        !           405:                          String title, String icon) {
        !           406:     ToolbarButton button = new ToolbarButton(title, icon,
        !           407:         null, paragraphButtonUpdate, data:new ToolbarStyleInfo(doc.hiddenParaRefs, cssName, cssValue));
        !           408:     button.action = () {
        !           409:       if (button.selected) {
        !           410:         DNHiddenP.removeStyleFromSelection(cssName);
        !           411:       } else {
        !           412:         DNHiddenP.applyStyleToSelection(cssName, cssValue);
        !           413:       }
        !           414:     };
        !           415:     alignBox.add(button);
        !           416:   }
        !           417:   
        !           418:   static void paragraphButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           419:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           420:     ToolbarStyleInfo info = button.data;
        !           421:     bool foundAncestor = false;
        !           422:     for (DaxeNode n = parent; n != null; n = n.parent) {
        !           423:       if (doc.hiddenParaRefs.contains(n.ref)) {
        !           424:         if ((n as DNHiddenP).matchesCss(info.cssName, info.cssValue)) {
        !           425:           foundAncestor = true;
        !           426:           break;
        !           427:         }
        !           428:       }
        !           429:     }
        !           430:     if (foundAncestor) {
        !           431:       button.enable();
        !           432:       button.select();
        !           433:     } else {
        !           434:       if (selectedNode != null && doc.hiddenParaRefs.contains(selectedNode.ref) &&
        !           435:           (selectedNode as DNHiddenP).matchesCss(info.cssName, info.cssValue)) {
        !           436:         button.select();
        !           437:       } else {
        !           438:         button.deselect();
        !           439:       }
        !           440:       if (DNHiddenP.paragraphsInSelection().length > 0)
        !           441:         button.enable();
        !           442:       else
        !           443:         button.disable();
        !           444:     }
        !           445:   }
        !           446:   
        !           447:   static void listButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           448:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           449:     // toggle list button
        !           450:     ToolbarStyleInfo info = button.data;
        !           451:     List<x.Element> refs = info.possibleRefs;
        !           452:     bool foundAncestor = false;
        !           453:     for (DaxeNode n = parent; n != null; n = n.parent) {
        !           454:       if (refs.contains(n.ref)) {
        !           455:         foundAncestor = true;
        !           456:         break;
        !           457:       }
        !           458:     }
        !           459:     if (foundAncestor) {
        !           460:       button.enable();
        !           461:       button.select();
        !           462:     } else {
        !           463:       button.deselect();
        !           464:       if (info.findValidRef(validRefs))
        !           465:         button.enable();
        !           466:       else
        !           467:         button.disable();
        !           468:     }
        !           469:   }
        !           470:   
        !           471:   static void riseListLevelButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           472:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           473:     Position start = page.getSelectionStart();
        !           474:     DaxeNode dn = start.dn;
        !           475:     while (dn != null && dn is! DNWItem)
        !           476:       dn = dn.parent;
        !           477:     if (dn != null)
        !           478:       button.enable();
        !           479:     else
        !           480:       button.disable();
        !           481:   }
        !           482:   
        !           483:   static void lowerListLevelButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           484:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           485:     Position start = page.getSelectionStart();
        !           486:     DaxeNode dn = start.dn;
        !           487:     while (dn != null && dn is! DNWItem)
        !           488:       dn = dn.parent;
        !           489:     if (dn == null || dn.previousSibling == null)
        !           490:       button.disable();
        !           491:     else
        !           492:       button.enable();
        !           493:   }
        !           494:   
        !           495:   static void insertLinkButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           496:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           497:     ToolbarStyleInfo info = button.data;
        !           498:     if (page.getSelectionStart().dn is DNText && info.findValidRef(validRefs))
        !           499:       button.enable();
        !           500:     else
        !           501:       button.disable();
        !           502:   }
        !           503:   
        !           504:   static void removeLinkButtonUpdate(ToolbarButton button, DaxeNode parent, DaxeNode selectedNode,
        !           505:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           506:     ToolbarStyleInfo info = button.data;
        !           507:     List<x.Element> refs = info.possibleRefs;
        !           508:     bool foundAncestor = false;
        !           509:     for (x.Element possibleRef in refs) {
        !           510:       if (ancestorRefs.contains(possibleRef)) {
        !           511:         foundAncestor = true;
        !           512:         break;
        !           513:       }
        !           514:     }
        !           515:     if (foundAncestor)
        !           516:       button.enable();
        !           517:     else
        !           518:       button.disable();
        !           519:   }
        !           520:   
        !           521:   static void styleMenuUpdate(ToolbarMenu tbmenu, DaxeNode parent, DaxeNode selectedNode,
        !           522:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           523:     Menu menu = tbmenu.menu;
        !           524:     MenuItem selectedItem = null;
        !           525:     for (MenuItem menuItem in menu.items) {
        !           526:       if (menuItem.data is ToolbarStyleInfo) {
        !           527:         ToolbarStyleInfo info = menuItem.data;
        !           528:         x.Element ref = info.possibleRefs[0];
        !           529:         String cssName = info.cssName;
        !           530:         String cssValue = info.cssValue;
        !           531:         if (doc.hiddenParaRefs.contains(ref)) {
        !           532:           // paragraph style
        !           533:           bool foundAncestor = false;
        !           534:           for (DaxeNode n = parent; n != null; n = n.parent) {
        !           535:             if (doc.hiddenParaRefs.contains(n.ref) && (n as DNHiddenP).matchesCss(cssName, cssValue)) {
        !           536:               foundAncestor = true;
        !           537:               break;
        !           538:             }
        !           539:           }
        !           540:           if (foundAncestor) {
        !           541:             menuItem.enable();
        !           542:             selectedItem = menuItem;
        !           543:             menuItem.check();
        !           544:           } else {
        !           545:             if (selectedNode != null && doc.hiddenParaRefs.contains(selectedNode.ref) &&
        !           546:                 (selectedNode as DNHiddenP).matchesCss(cssName, cssValue)) {
        !           547:               selectedItem = menuItem;
        !           548:               menuItem.check();
        !           549:             } else {
        !           550:               menuItem.uncheck();
        !           551:             }
        !           552:             if (DNHiddenP.paragraphsInSelection().length > 0)
        !           553:               menuItem.enable();
        !           554:             else
        !           555:               menuItem.disable();
        !           556:           }
        !           557:         } else if (doc.cfg.elementDisplayType(ref) == 'style') {
        !           558:           // DNStyle
        !           559:           if (ancestorRefs.contains(ref)) {
        !           560:             menuItem.enable();
        !           561:             selectedItem = menuItem;
        !           562:           } else {
        !           563:             if (selectedNode != null && ref == selectedNode.ref)
        !           564:               selectedItem = menuItem;
        !           565:             if (validRefs.contains(ref))
        !           566:               menuItem.enable();
        !           567:             else
        !           568:               menuItem.disable();
        !           569:           }
        !           570:         } else if (doc.cfg.elementDisplayType(ref) == 'stylespan') {
        !           571:           // DNSpanStyle
        !           572:           bool foundAncestor = false;
        !           573:           for (DaxeNode n = parent; n != null; n = n.parent) {
        !           574:             if (n.ref == ref && (n as DNStyleSpan).matchesCss(cssName, cssValue)) {
        !           575:               foundAncestor = true;
        !           576:               break;
        !           577:             }
        !           578:           }
        !           579:           if (foundAncestor) {
        !           580:             menuItem.enable();
        !           581:             selectedItem = menuItem;
        !           582:             menuItem.check();
        !           583:           } else {
        !           584:             if (selectedNode != null && ref == selectedNode.ref &&
        !           585:                 (selectedNode as DNStyleSpan).matchesCss(cssName, cssValue)) {
        !           586:               selectedItem = menuItem;
        !           587:               menuItem.check();
        !           588:             } else {
        !           589:               menuItem.uncheck();
        !           590:             }
        !           591:             if (validRefs.contains(ref))
        !           592:               menuItem.enable();
        !           593:             else
        !           594:               menuItem.disable();
        !           595:           }
        !           596:         } else if (ref != null) {
        !           597:           // element insert
        !           598:           if (validRefs.contains(ref))
        !           599:             menuItem.enable();
        !           600:           else
        !           601:             menuItem.disable();
        !           602:         }
        !           603:       }
        !           604:     }
        !           605:     if (selectedItem == null)
        !           606:       menu.title = tbmenu.title;
        !           607:     else
        !           608:       menu.title = selectedItem.title;
        !           609:   }
        !           610:   
        !           611:   static void insertMenuUpdate(ToolbarMenu tbmenu, DaxeNode parent, DaxeNode selectedNode,
        !           612:                              List<x.Element> validRefs, List<x.Element> ancestorRefs) {
        !           613:     Menu menu = tbmenu.menu;
        !           614:     for (MenuItem menuItem in menu.items) {
        !           615:       if (menuItem.data is ToolbarStyleInfo) {
        !           616:         ToolbarStyleInfo info = menuItem.data;
        !           617:         List<x.Element> refs = info.possibleRefs;
        !           618:         if (refs != null && refs.length > 0) {
        !           619:           // element insert
        !           620:           if (info.findValidRef(validRefs))
        !           621:             menuItem.enable();
        !           622:           else
        !           623:             menuItem.disable();
        !           624:         }
        !           625:       }
        !           626:     }
        !           627:   }
        !           628:   
        !           629:   void update(DaxeNode parent, List<x.Element> validRefs) {
        !           630:     List<x.Element> ancestorRefs = new List<x.Element>();
        !           631:     for (DaxeNode n = parent; n != null; n = n.parent)
        !           632:       ancestorRefs.add(n.ref);
        !           633:     DaxeNode selectedNode = null;// will be !=null when the selection matches a full element
        !           634:     Position start = page.getSelectionStart();
        !           635:     Position end = page.getSelectionEnd();
        !           636:     if (start.dn is! DNText && start.dn.offsetLength > start.dnOffset) {
        !           637:       if (end == new Position(start.dn, start.dnOffset + 1))
        !           638:         selectedNode = start.dn.childAtOffset(start.dnOffset);
        !           639:     }
        !           640:     // update buttons
        !           641:     for (ToolbarButton button in buttons) {
        !           642:       if (button.update != null)
        !           643:         button.update(button, parent, selectedNode, validRefs, ancestorRefs);
        !           644:     }
        !           645:     // update menus
        !           646:     for (ToolbarItem tbitem in items) {
        !           647:       if (tbitem is ToolbarMenu) {
        !           648:         tbitem.update(tbitem, parent, selectedNode, validRefs, ancestorRefs);
        !           649:       }
        !           650:     }
        !           651:   }
        !           652:   
        !           653: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>