Lines 42-49
Link Here
|
42 |
import com.sun.rave.designtime.Position; |
42 |
import com.sun.rave.designtime.Position; |
43 |
import com.sun.rave.designtime.event.DesignContextListener; |
43 |
import com.sun.rave.designtime.event.DesignContextListener; |
44 |
import com.sun.rave.designtime.markup.MarkupDesignBean; |
44 |
import com.sun.rave.designtime.markup.MarkupDesignBean; |
|
|
45 |
import java.util.ArrayList; |
46 |
import java.util.HashMap; |
47 |
import java.util.List; |
48 |
import java.util.Map; |
45 |
import org.netbeans.modules.visualweb.designer.html.HtmlTag; |
49 |
import org.netbeans.modules.visualweb.designer.html.HtmlTag; |
46 |
import org.openide.ErrorManager; |
50 |
import org.openide.ErrorManager; |
|
|
51 |
import org.w3c.dom.Attr; |
52 |
import org.w3c.dom.NamedNodeMap; |
47 |
|
53 |
|
48 |
/** |
54 |
/** |
49 |
* XXX Moved from designer. |
55 |
* XXX Moved from designer. |
Lines 689-708
Link Here
|
689 |
// Node previouslyRendered = ((RaveElement)bean.getElement()).getRendered(); |
695 |
// Node previouslyRendered = ((RaveElement)bean.getElement()).getRendered(); |
690 |
Node previouslyRendered = MarkupService.getRenderedElementForElement(bean.getElement()); |
696 |
Node previouslyRendered = MarkupService.getRenderedElementForElement(bean.getElement()); |
691 |
|
697 |
|
692 |
if (!processDelete(bean)) { |
698 |
// if (!processDelete(bean)) { |
693 |
processRefresh(); |
699 |
// processRefresh(); |
694 |
// webform.getPane().getPaneUI().modelChanged(); |
700 |
//// webform.getPane().getPaneUI().modelChanged(); |
695 |
jsfForm.modelChanged(); |
701 |
// jsfForm.modelChanged(); |
696 |
|
702 |
// |
697 |
return; |
703 |
// return; |
698 |
} |
704 |
// } |
699 |
|
705 |
// |
700 |
// Insert new version of component |
706 |
// // Insert new version of component |
701 |
if (!processInsert(bean)) { |
707 |
// if (!processInsert(bean)) { |
|
|
708 |
// processRefresh(); |
709 |
//// webform.getPane().getPaneUI().modelChanged(); |
710 |
// jsfForm.modelChanged(); |
711 |
// |
712 |
// return; |
713 |
// } |
714 |
if (!processUpdate(bean)) { |
702 |
processRefresh(); |
715 |
processRefresh(); |
703 |
// webform.getPane().getPaneUI().modelChanged(); |
|
|
704 |
jsfForm.modelChanged(); |
716 |
jsfForm.modelChanged(); |
705 |
|
|
|
706 |
return; |
717 |
return; |
707 |
} |
718 |
} |
708 |
|
719 |
|
Lines 712-732
Link Here
|
712 |
Node rendered = MarkupService.getRenderedElementForElement(bean.getElement()); |
723 |
Node rendered = MarkupService.getRenderedElementForElement(bean.getElement()); |
713 |
|
724 |
|
714 |
if (rendered != null) { |
725 |
if (rendered != null) { |
715 |
if (rendered != previouslyRendered) { |
726 |
// if (rendered != previouslyRendered) { |
716 |
Node parent = rendered.getParentNode(); |
727 |
// Node parent = rendered.getParentNode(); |
717 |
// PageBox pageBox = webform.getPane().getPaneUI().getPageBox(); |
728 |
//// PageBox pageBox = webform.getPane().getPaneUI().getPageBox(); |
718 |
// pageBox.changed(rendered, parent, false); |
729 |
//// pageBox.changed(rendered, parent, false); |
719 |
jsfForm.nodeChanged(rendered, parent, false); |
730 |
// jsfForm.nodeChanged(rendered, parent, false); |
720 |
} else { |
731 |
// } else { |
721 |
// We've re-rendered but the bean-reference doesn't point |
732 |
// // We've re-rendered but the bean-reference doesn't point |
722 |
// to a new node. This means that the component must have |
733 |
// // to a new node. This means that the component must have |
723 |
// supplied bogus component references when rendering. |
734 |
// // supplied bogus component references when rendering. |
724 |
// Note: With wrong element referenced we're not well off anyway - |
735 |
// // Note: With wrong element referenced we're not well off anyway - |
725 |
// the component won't be selectable! |
736 |
// // the component won't be selectable! |
726 |
// PageBox pageBox = webform.getPane().getPaneUI().getPageBox(); |
737 |
//// PageBox pageBox = webform.getPane().getPaneUI().getPageBox(); |
727 |
// webform.getPane().getPaneUI().modelChanged(); |
738 |
//// webform.getPane().getPaneUI().modelChanged(); |
728 |
jsfForm.modelChanged(); |
739 |
// // XXX Now it means, that the node was updated, see the tryUpdateOriginalNode. |
729 |
} |
740 |
// jsfForm.modelChanged(); |
|
|
741 |
// } |
742 |
// Now the original node could be reused (see the tryUpdateOriginalNode). |
743 |
Node parent = rendered.getParentNode(); |
744 |
jsfForm.nodeChanged(rendered, parent, false); |
730 |
} else if (previouslyRendered != null) { |
745 |
} else if (previouslyRendered != null) { |
731 |
// It was just deleted - for example when you change a component by |
746 |
// It was just deleted - for example when you change a component by |
732 |
// switching off its "rendered" property |
747 |
// switching off its "rendered" property |
Lines 793-798
Link Here
|
793 |
InSyncServiceProvider.get().getHtmlStream(html)); |
808 |
InSyncServiceProvider.get().getHtmlStream(html)); |
794 |
} |
809 |
} |
795 |
} |
810 |
} |
|
|
811 |
} |
812 |
|
813 |
private boolean processUpdate(MarkupDesignBean bean) { |
814 |
// Deleting |
815 |
// if (!processDelete(bean)) { |
816 |
// return false; |
817 |
// } |
818 |
|
819 |
Element element = bean.getElement(); |
820 |
Node rendered = MarkupService.getRenderedElementForElement(element); |
821 |
if (rendered == null) { |
822 |
return false; |
823 |
} |
824 |
|
825 |
Node parent = rendered.getParentNode(); |
826 |
// Find leftmost node |
827 |
Node curr = rendered.getPreviousSibling(); |
828 |
while (curr != null) { |
829 |
if (curr.getNodeType() == Node.ELEMENT_NODE) { |
830 |
Element xel = (Element)curr; |
831 |
if (MarkupUnit.getMarkupDesignBeanForElement(xel) == bean) { |
832 |
rendered = curr; |
833 |
} else { |
834 |
break; |
835 |
} |
836 |
} |
837 |
curr = curr.getPreviousSibling(); |
838 |
} |
839 |
|
840 |
deleteParent = parent; |
841 |
|
842 |
List<Node> originalNodes = new ArrayList<Node>(); |
843 |
Node before = null; |
844 |
// TODO - I ought to assert here that the parent is in the |
845 |
// HTML DOM I'm attached to |
846 |
// Remove all the rendered nodes |
847 |
while (rendered != null) { |
848 |
// Node before = rendered.getNextSibling(); |
849 |
before = rendered.getNextSibling(); |
850 |
// parent.removeChild(rendered); |
851 |
originalNodes.add(rendered); |
852 |
if (before == null) { |
853 |
break; |
854 |
} |
855 |
// See if I need to delete additional siblings. This is slightly |
856 |
// tricky because I can't just look at the next sibling. Components |
857 |
// may separate tags with text nodes that are associated with the |
858 |
// parent rather than the component being rendered; for example, |
859 |
// a component renderer may do this: |
860 |
// writer.startElement(foo, component); |
861 |
// writer.endElement(foo); |
862 |
// writer.write("\n"); |
863 |
// writer.startElement(bar, component); |
864 |
// .... |
865 |
// Note that we want to delete both foo and bar even though there's |
866 |
// a text node in between which is not associated with the component |
867 |
// since it's not within a startElement for "component", it's within |
868 |
// the element for the parent these children (foo and bar) are being |
869 |
// added to. |
870 |
// So, my strategy is to peek ahead and see if the next element |
871 |
// found is associated with the same DesignBean, and if so, delete |
872 |
// everything up to it. |
873 |
if (!moreElements(before, bean)) { |
874 |
break; |
875 |
} |
876 |
rendered = before; |
877 |
} |
878 |
|
879 |
// Inserting |
880 |
// if (!processInsert(bean)) { |
881 |
// return false; |
882 |
// } |
883 |
|
884 |
// XXX TODO There is not needed webform here. |
885 |
// Render the new element |
886 |
// TODO - this should not necessarily have to involve FacesBeans! |
887 |
// XXX Do not mark the new nodes as rendered for this case yet. |
888 |
DocumentFragment df = jsfForm.renderMarkupDesignBean(bean, false); |
889 |
|
890 |
// This seems to be not the correct place. |
891 |
// // XXX FIXME Is this correct here? |
892 |
// jsfForm.updateErrorsInComponent(); |
893 |
|
894 |
if (DEBUG) { |
895 |
System.out.println("Got fragment from insert render html: " + |
896 |
InSyncServiceProvider.get().getHtmlStream(df)); |
897 |
} |
898 |
|
899 |
List<Node> newNodes = new ArrayList<Node>(); |
900 |
|
901 |
if (df != null) { |
902 |
// Insert nodes into the rendered dom |
903 |
NodeList nl = df.getChildNodes(); |
904 |
int num = nl.getLength(); |
905 |
|
906 |
if (num == 0) { |
907 |
// Rendered to nothing. This happens if you switch the Rendered attribute |
908 |
// to off for example - this comes in as a change request rather than |
909 |
// as a delete request - but we need to go and update the source element's |
910 |
// rendered reference since it would now be obsolete in the future |
911 |
// and we shouldn't attempt to use it |
912 |
// ((RaveElement)bean.getElement()).setRendered(null); |
913 |
// XXX FIXME Modifying the data structure! |
914 |
MarkupService.setRenderedElementForElement(bean.getElement(), null); |
915 |
return true; |
916 |
} |
917 |
|
918 |
// Can't remove from a NodeList while iterating over it - causes |
919 |
// surprises like null siblings. So we need to copy first. |
920 |
int n = nl.getLength(); |
921 |
Node[] nodes = new Node[n]; |
922 |
|
923 |
for (int i = 0; i < n; i++) { |
924 |
nodes[i] = nl.item(i); |
925 |
} |
926 |
|
927 |
for (int i = 0; i < n; i++) { |
928 |
Node nn = nodes[i]; |
929 |
if (DEBUG) { |
930 |
if (nn != null) { |
931 |
System.out.println("next node is: " + InSyncServiceProvider.get().getHtmlStream(nn)); |
932 |
System.out.println("Fragment is now: " + InSyncServiceProvider.get().getHtmlStream(df)); |
933 |
} |
934 |
} |
935 |
|
936 |
if (nn != null) { |
937 |
assert !isJspNode(nn); |
938 |
// parent.insertBefore(nn, before); |
939 |
newNodes.add(nn); |
940 |
} |
941 |
} |
942 |
} else { |
943 |
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, |
944 |
new NullPointerException("Null DocumentFragment for JsfForm, jsfForm=" + jsfForm)); // NOI18N |
945 |
return false; |
946 |
} |
947 |
|
948 |
if (originalNodes.size() == 1 && newNodes.size() == 1) { |
949 |
Node originalNode = originalNodes.get(0); |
950 |
Node newNode = newNodes.get(0); |
951 |
if (tryUpdateOriginalNode(originalNode, newNode)) { |
952 |
// XXX The original nodes are updated, do not mark the new as rendered, they are not used. |
953 |
return true; |
954 |
} else { |
955 |
parent.replaceChild(newNode, originalNode); |
956 |
} |
957 |
} else { |
958 |
for (Node toRemove : originalNodes) { |
959 |
parent.removeChild(toRemove); |
960 |
} |
961 |
for (Node toAdd : newNodes) { |
962 |
parent.insertBefore(toAdd, before); |
963 |
} |
964 |
} |
965 |
|
966 |
// XXX Mark the newly used nodes as rendered. |
967 |
MarkupService.markRenderedNodes(df); |
968 |
|
969 |
return true; |
970 |
} |
971 |
|
972 |
private static boolean tryUpdateOriginalNode(Node originalNode, Node newNode) { |
973 |
if (originalNode.getNodeType() != newNode.getNodeType()) { |
974 |
return false; |
975 |
} |
976 |
|
977 |
if (originalNode.isEqualNode(newNode)) { |
978 |
return true; |
979 |
} |
980 |
|
981 |
// Update children |
982 |
NodeList originalNodeChildren = originalNode.getChildNodes(); |
983 |
NodeList newNodeChildren = newNode.getChildNodes(); |
984 |
if (originalNodeChildren == null) { |
985 |
if (newNodeChildren != null) { |
986 |
return false; |
987 |
} |
988 |
} else { |
989 |
if (newNodeChildren == null) { |
990 |
return false; |
991 |
} |
992 |
int originalNodeChildrenSize = originalNodeChildren.getLength(); |
993 |
int newNodeChildrenSize = newNodeChildren.getLength(); |
994 |
if (originalNodeChildrenSize != newNodeChildrenSize) { |
995 |
return false; |
996 |
} |
997 |
|
998 |
for (int i = 0; i < originalNodeChildrenSize; i++) { |
999 |
boolean childOK = tryUpdateOriginalNode(originalNodeChildren.item(i), newNodeChildren.item(i)); |
1000 |
if (!childOK) { |
1001 |
return false; |
1002 |
} |
1003 |
} |
1004 |
} |
1005 |
|
1006 |
// Update value. |
1007 |
String originalValue = originalNode.getNodeValue(); |
1008 |
String newValue = newNode.getNodeValue(); |
1009 |
if ((originalValue == null && newValue != null) |
1010 |
|| (originalValue != null && !originalValue.equals(newValue))) { |
1011 |
originalNode.setNodeValue(newValue); |
1012 |
} |
1013 |
|
1014 |
// Update attributes. |
1015 |
if (originalNode instanceof Element && newNode instanceof Element) { |
1016 |
Element originalElement = (Element)originalNode; |
1017 |
Element newElement = (Element)newNode; |
1018 |
|
1019 |
Map<String, Attr> originalMap = getAttributesMap(originalElement); |
1020 |
Map<String, Attr> newMap = getAttributesMap(newElement); |
1021 |
|
1022 |
// Remove redundant attributes. |
1023 |
for (String name : originalMap.keySet()) { |
1024 |
if (newMap.containsKey(name)) { |
1025 |
continue; |
1026 |
} |
1027 |
originalElement.removeAttribute(name); |
1028 |
} |
1029 |
// Add/update the remaining attributes. |
1030 |
for (String name : newMap.keySet()) { |
1031 |
Attr newAttribute = newMap.get(name); |
1032 |
Attr originalAttribute = originalMap.get(name); |
1033 |
|
1034 |
if (originalAttribute == null) { |
1035 |
originalElement.setAttributeNode((Attr)newAttribute.cloneNode(false)); |
1036 |
} else { |
1037 |
String oldAttributeValue = originalAttribute.getValue(); |
1038 |
String newAttributeValue = newAttribute.getValue(); |
1039 |
if (newAttributeValue == null) { |
1040 |
if (oldAttributeValue != null) { |
1041 |
originalElement.removeAttribute(name); |
1042 |
} |
1043 |
} else { |
1044 |
if (!newAttributeValue.equals(oldAttributeValue)) { |
1045 |
originalElement.setAttributeNode((Attr)newAttribute.cloneNode(false)); |
1046 |
} |
1047 |
} |
1048 |
} |
1049 |
} |
1050 |
} |
1051 |
|
1052 |
return true; |
1053 |
} |
1054 |
|
1055 |
private static Map<String, Attr> getAttributesMap(Element element) { |
1056 |
NamedNodeMap attributes = element.getAttributes(); |
1057 |
Map<String, Attr> attributesMap = new HashMap<String, Attr>(); |
1058 |
int size = attributes == null ? 0 : attributes.getLength(); |
1059 |
for (int i = 0; i < size; i++) { |
1060 |
Node attr = attributes.item(i); |
1061 |
if (attr instanceof Attr) { |
1062 |
Attr attribute = (Attr)attr; |
1063 |
attributesMap.put(attribute.getName(), attribute); |
1064 |
} |
1065 |
} |
1066 |
return attributesMap; |
796 |
} |
1067 |
} |
797 |
|
1068 |
|
798 |
/** |
1069 |
/** |