mirror of https://github.com/anoshenko/rui.git
				
				
				
			Added OpenURL function, optimisation
This commit is contained in:
		
							parent
							
								
									705a9c0e37
								
							
						
					
					
						commit
						7c860c54b9
					
				|  | @ -1,12 +1,13 @@ | |||
| # v0.9.0 | ||||
| 
 | ||||
| * Requared go 1.18 | ||||
| * Requires go 1.18 or higher | ||||
| * The "interface{}" type replaced by "any" | ||||
| * Added "overflow", "arrow", "arrow-align", "arrow-size", "arrow-width", and "arrow-offset" properties  | ||||
| * Added "@ruiArrowSize" and "@ruiArrowWidth" constants to the default theme | ||||
| * Added Transition, Transitions, and SetTransition functions to the ViewStyle interface | ||||
| * Added GetOverflow, IsTimingFunctionValid, and GetTransitions functions | ||||
| * Changed GetTransition functions | ||||
| * Added the OpenURL function to the Session interface | ||||
| 
 | ||||
| # v0.8.0 | ||||
| 
 | ||||
|  |  | |||
|  | @ -400,7 +400,7 @@ func (animation *animationData) animationCSS(session Session) string { | |||
| 
 | ||||
| 	buffer.WriteString(animation.keyFramesName) | ||||
| 
 | ||||
| 	if duration, _ := floatProperty(animation, Duration, session, 1); duration > 0 { | ||||
| 	if duration, ok := floatProperty(animation, Duration, session, 1); ok && duration > 0 { | ||||
| 		buffer.WriteString(fmt.Sprintf(" %gs ", duration)) | ||||
| 	} else { | ||||
| 		buffer.WriteString(" 1s ") | ||||
|  | @ -408,7 +408,7 @@ func (animation *animationData) animationCSS(session Session) string { | |||
| 
 | ||||
| 	buffer.WriteString(animation.timingFunctionCSS(session)) | ||||
| 
 | ||||
| 	if delay, _ := floatProperty(animation, Delay, session, 0); delay > 0 { | ||||
| 	if delay, ok := floatProperty(animation, Delay, session, 0); ok && delay > 0 { | ||||
| 		buffer.WriteString(fmt.Sprintf(" %gs", delay)) | ||||
| 	} else { | ||||
| 		buffer.WriteString(" 0s") | ||||
|  | @ -438,7 +438,7 @@ func (animation *animationData) animationCSS(session Session) string { | |||
| 
 | ||||
| func (animation *animationData) transitionCSS(buffer *strings.Builder, session Session) { | ||||
| 
 | ||||
| 	if duration, _ := floatProperty(animation, Duration, session, 1); duration > 0 { | ||||
| 	if duration, ok := floatProperty(animation, Duration, session, 1); ok && duration > 0 { | ||||
| 		buffer.WriteString(fmt.Sprintf(" %gs ", duration)) | ||||
| 	} else { | ||||
| 		buffer.WriteString(" 1s ") | ||||
|  | @ -446,7 +446,7 @@ func (animation *animationData) transitionCSS(buffer *strings.Builder, session S | |||
| 
 | ||||
| 	buffer.WriteString(animation.timingFunctionCSS(session)) | ||||
| 
 | ||||
| 	if delay, _ := floatProperty(animation, Delay, session, 0); delay > 0 { | ||||
| 	if delay, ok := floatProperty(animation, Delay, session, 0); ok && delay > 0 { | ||||
| 		buffer.WriteString(fmt.Sprintf(" %gs", delay)) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -114,12 +114,13 @@ func (picker *numberPickerData) set(tag string, value any) bool { | |||
| 		oldValue := GetNumberPickerValue(picker, "") | ||||
| 		min, max := GetNumberPickerMinMax(picker, "") | ||||
| 		if picker.setFloatProperty(NumberPickerValue, value, min, max) { | ||||
| 			if newValue := GetNumberPickerValue(picker, ""); oldValue != newValue { | ||||
| 			if f, ok := floatProperty(picker, NumberPickerValue, picker.Session(), min); ok && f != oldValue { | ||||
| 				newValue, _ := floatTextProperty(picker, NumberPickerValue, picker.Session(), min) | ||||
| 				if picker.created { | ||||
| 					picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), newValue)) | ||||
| 					picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newValue)) | ||||
| 				} | ||||
| 				for _, listener := range picker.numberChangedListeners { | ||||
| 					listener(picker, newValue) | ||||
| 					listener(picker, f) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
|  | @ -239,7 +240,7 @@ func (picker *numberPickerData) handleCommand(self View, command string, data Da | |||
| 		if text, ok := data.PropertyValue("text"); ok { | ||||
| 			if value, err := strconv.ParseFloat(text, 32); err == nil { | ||||
| 				oldValue := GetNumberPickerValue(picker, "") | ||||
| 				picker.properties[NumberPickerValue] = value | ||||
| 				picker.properties[NumberPickerValue] = text | ||||
| 				if value != oldValue { | ||||
| 					for _, listener := range picker.numberChangedListeners { | ||||
| 						listener(picker, value) | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| package rui | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | @ -238,6 +239,30 @@ func floatProperty(properties Properties, tag string, session Session, defaultVa | |||
| 	return valueToFloat(properties.getRaw(tag), session, defaultValue) | ||||
| } | ||||
| 
 | ||||
| func valueToFloatText(value any, session Session, defaultValue float64) (string, bool) { | ||||
| 	if value != nil { | ||||
| 		switch value := value.(type) { | ||||
| 		case float64: | ||||
| 			return fmt.Sprintf("%g", value), true | ||||
| 
 | ||||
| 		case string: | ||||
| 			if text, ok := session.resolveConstants(value); ok { | ||||
| 				if _, err := strconv.ParseFloat(text, 64); err != nil { | ||||
| 					ErrorLog(err.Error()) | ||||
| 					return fmt.Sprintf("%g", defaultValue), false | ||||
| 				} | ||||
| 				return text, true | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return fmt.Sprintf("%g", defaultValue), false | ||||
| } | ||||
| 
 | ||||
| func floatTextProperty(properties Properties, tag string, session Session, defaultValue float64) (string, bool) { | ||||
| 	return valueToFloatText(properties.getRaw(tag), session, defaultValue) | ||||
| } | ||||
| 
 | ||||
| func valueToRange(value any, session Session) (Range, bool) { | ||||
| 	if value != nil { | ||||
| 		switch value := value.(type) { | ||||
|  |  | |||
|  | @ -730,6 +730,12 @@ func (properties *propertyList) setFloatProperty(tag string, value any, min, max | |||
| 				ErrorLog(err.Error()) | ||||
| 				return false | ||||
| 			} | ||||
| 			if f < min || f > max { | ||||
| 				ErrorLogF(`"%T" out of range of "%s" property`, value, tag) | ||||
| 				return false | ||||
| 			} | ||||
| 			properties.properties[tag] = value | ||||
| 			return true | ||||
| 
 | ||||
| 		case float32: | ||||
| 			f = float64(value) | ||||
|  |  | |||
							
								
								
									
										11
									
								
								session.go
								
								
								
								
							
							
						
						
									
										11
									
								
								session.go
								
								
								
								
							|  | @ -2,6 +2,7 @@ package rui | |||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/url" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
|  | @ -69,6 +70,8 @@ type Session interface { | |||
| 	DownloadFile(path string) | ||||
| 	//DownloadFileData downloads (saves) on the client side a file with a specified name and specified content.
 | ||||
| 	DownloadFileData(filename string, data []byte) | ||||
| 	// OpenURL opens the url in the new browser tab
 | ||||
| 	OpenURL(url string) | ||||
| 
 | ||||
| 	registerAnimation(props []AnimatedProperty) string | ||||
| 
 | ||||
|  | @ -448,3 +451,11 @@ func (session *sessionData) SetTitleColor(color Color) { | |||
| func (session *sessionData) RemoteAddr() string { | ||||
| 	return session.brige.remoteAddr() | ||||
| } | ||||
| 
 | ||||
| func (session *sessionData) OpenURL(urlStr string) { | ||||
| 	if _, err := url.ParseRequestURI(urlStr); err != nil { | ||||
| 		ErrorLog(err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	session.runScript(`window.open("` + urlStr + `", "_blank");`) | ||||
| } | ||||
|  |  | |||
|  | @ -622,7 +622,7 @@ func (table *tableViewData) propertyChanged(tag string) { | |||
| 				updateProperty(htmlID, "tabindex", "0", session) | ||||
| 				updateProperty(htmlID, "onfocus", "tableViewFocusEvent(this, event)", session) | ||||
| 				updateProperty(htmlID, "onblur", "tableViewBlurEvent(this, event)", session) | ||||
| 				updateProperty(htmlID, "data-selection", "cell", session) | ||||
| 				updateProperty(htmlID, "data-selection", "row", session) | ||||
| 				updateProperty(htmlID, "data-focusitemstyle", table.currentStyle(), session) | ||||
| 				updateProperty(htmlID, "data-bluritemstyle", table.currentInactiveStyle(), session) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| package rui | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
|  | @ -90,9 +89,9 @@ func (player *videoPlayerData) set(tag string, value any) bool { | |||
| 	if player.mediaPlayerData.set(tag, value) { | ||||
| 		session := player.Session() | ||||
| 		updateSize := func(cssTag string) { | ||||
| 			if size, ok := floatProperty(player, tag, session, 0); ok { | ||||
| 				if size > 0 { | ||||
| 					updateProperty(player.htmlID(), cssTag, fmt.Sprintf("%g", size), session) | ||||
| 			if size, ok := floatTextProperty(player, tag, session, 0); ok { | ||||
| 				if size != "0" { | ||||
| 					updateProperty(player.htmlID(), cssTag, size, session) | ||||
| 				} else { | ||||
| 					removeProperty(player.htmlID(), cssTag, session) | ||||
| 				} | ||||
|  | @ -122,12 +121,16 @@ func (player *videoPlayerData) htmlProperties(self View, buffer *strings.Builder | |||
| 
 | ||||
| 	session := player.Session() | ||||
| 
 | ||||
| 	if size, ok := floatProperty(player, VideoWidth, session, 0); ok && size > 0 { | ||||
| 		buffer.WriteString(fmt.Sprintf(` width="%g"`, size)) | ||||
| 	if size, ok := floatTextProperty(player, VideoWidth, session, 0); ok && size != "0" { | ||||
| 		buffer.WriteString(` width="`) | ||||
| 		buffer.WriteString(size) | ||||
| 		buffer.WriteString(`"`) | ||||
| 	} | ||||
| 
 | ||||
| 	if size, ok := floatProperty(player, VideoHeight, session, 0); ok && size > 0 { | ||||
| 		buffer.WriteString(fmt.Sprintf(` height="%g"`, size)) | ||||
| 	if size, ok := floatTextProperty(player, VideoHeight, session, 0); ok && size != "0" { | ||||
| 		buffer.WriteString(` height="`) | ||||
| 		buffer.WriteString(size) | ||||
| 		buffer.WriteString(`"`) | ||||
| 	} | ||||
| 
 | ||||
| 	if url, ok := stringProperty(player, Poster, session); ok && url != "" { | ||||
|  |  | |||
							
								
								
									
										4
									
								
								view.go
								
								
								
								
							
							
						
						
									
										4
									
								
								view.go
								
								
								
								
							|  | @ -655,8 +655,8 @@ func viewPropertyChanged(view *viewData, tag string) { | |||
| 
 | ||||
| 	for _, floatTag := range []string{Opacity, ScaleX, ScaleY, ScaleZ, RotateX, RotateY, RotateZ} { | ||||
| 		if tag == floatTag { | ||||
| 			if f, ok := floatProperty(view, floatTag, session, 0); ok { | ||||
| 				updateCSSProperty(htmlID, floatTag, strconv.FormatFloat(f, 'g', -1, 64), session) | ||||
| 			if f, ok := floatTextProperty(view, floatTag, session, 0); ok { | ||||
| 				updateCSSProperty(htmlID, floatTag, f, session) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
|  |  | |||
|  | @ -180,20 +180,22 @@ func (filter *viewFilter) cssStyle(session Session) string { | |||
| 	buffer := allocStringBuilder() | ||||
| 	defer freeStringBuilder(buffer) | ||||
| 
 | ||||
| 	if value, ok := floatProperty(filter, Blur, session, 0); ok { | ||||
| 		size := SizeUnit{Type: SizeInPixel, Value: value} | ||||
| 	if value, ok := floatTextProperty(filter, Blur, session, 0); ok { | ||||
| 		buffer.WriteString(Blur) | ||||
| 		buffer.WriteRune('(') | ||||
| 		buffer.WriteString(size.cssString("0px")) | ||||
| 		buffer.WriteRune(')') | ||||
| 		buffer.WriteString(value) | ||||
| 		buffer.WriteString("px)") | ||||
| 	} | ||||
| 
 | ||||
| 	for _, tag := range []string{Brightness, Contrast, Saturate, Grayscale, Invert, Opacity, Sepia} { | ||||
| 		if value, ok := floatProperty(filter, tag, session, 0); ok { | ||||
| 		if value, ok := floatTextProperty(filter, tag, session, 0); ok { | ||||
| 			if buffer.Len() > 0 { | ||||
| 				buffer.WriteRune(' ') | ||||
| 			} | ||||
| 			buffer.WriteString(fmt.Sprintf("%s(%g%%)", tag, value)) | ||||
| 			buffer.WriteString(tag) | ||||
| 			buffer.WriteRune('(') | ||||
| 			buffer.WriteString(value) | ||||
| 			buffer.WriteString("%)") | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,9 +1,5 @@ | |||
| package rui | ||||
| 
 | ||||
| import ( | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// Perspective is the name of the SizeUnit property that determines the distance between the z = 0 plane
 | ||||
| 	// and the user in order to give a 3D-positioned element some perspective. Each 3D element
 | ||||
|  | @ -104,20 +100,6 @@ func getTranslate(style Properties, session Session) (SizeUnit, SizeUnit, SizeUn | |||
| 	return x, y, z | ||||
| } | ||||
| 
 | ||||
| func getScale(style Properties, session Session) (float64, float64, float64, bool) { | ||||
| 	scaleX, okX := floatProperty(style, ScaleX, session, 1) | ||||
| 	scaleY, okY := floatProperty(style, ScaleY, session, 1) | ||||
| 	scaleZ, okZ := floatProperty(style, ScaleZ, session, 1) | ||||
| 	return scaleX, scaleY, scaleZ, okX || okY || okZ | ||||
| } | ||||
| 
 | ||||
| func getRotateVector(style Properties, session Session) (float64, float64, float64) { | ||||
| 	rotateX, _ := floatProperty(style, RotateX, session, 1) | ||||
| 	rotateY, _ := floatProperty(style, RotateY, session, 1) | ||||
| 	rotateZ, _ := floatProperty(style, RotateZ, session, 1) | ||||
| 	return rotateX, rotateY, rotateZ | ||||
| } | ||||
| 
 | ||||
| func (style *viewStyle) transform(session Session) string { | ||||
| 
 | ||||
| 	buffer := allocStringBuilder() | ||||
|  | @ -133,7 +115,10 @@ func (style *viewStyle) transform(session Session) string { | |||
| 	} | ||||
| 
 | ||||
| 	x, y, z := getTranslate(style, session) | ||||
| 	scaleX, scaleY, scaleZ, scaleOK := getScale(style, session) | ||||
| 
 | ||||
| 	scaleX, okScaleX := floatTextProperty(style, ScaleX, session, 1) | ||||
| 	scaleY, okScaleY := floatTextProperty(style, ScaleY, session, 1) | ||||
| 
 | ||||
| 	if getTransform3D(style, session) { | ||||
| 		if x.Type != Auto || y.Type != Auto || z.Type != Auto { | ||||
| 			if buffer.Len() > 0 { | ||||
|  | @ -148,30 +133,34 @@ func (style *viewStyle) transform(session Session) string { | |||
| 			buffer.WriteRune(')') | ||||
| 		} | ||||
| 
 | ||||
| 		if scaleOK { | ||||
| 		scaleZ, okScaleZ := floatTextProperty(style, ScaleZ, session, 1) | ||||
| 		if okScaleX || okScaleY || okScaleZ { | ||||
| 			if buffer.Len() > 0 { | ||||
| 				buffer.WriteRune(' ') | ||||
| 			} | ||||
| 			buffer.WriteString(`scale3d(`) | ||||
| 			buffer.WriteString(strconv.FormatFloat(scaleX, 'g', -1, 64)) | ||||
| 			buffer.WriteString(scaleX) | ||||
| 			buffer.WriteRune(',') | ||||
| 			buffer.WriteString(strconv.FormatFloat(scaleY, 'g', -1, 64)) | ||||
| 			buffer.WriteString(scaleY) | ||||
| 			buffer.WriteRune(',') | ||||
| 			buffer.WriteString(strconv.FormatFloat(scaleZ, 'g', -1, 64)) | ||||
| 			buffer.WriteString(scaleZ) | ||||
| 			buffer.WriteRune(')') | ||||
| 		} | ||||
| 
 | ||||
| 		if angle, ok := angleProperty(style, Rotate, session); ok { | ||||
| 			rotateX, rotateY, rotateZ := getRotateVector(style, session) | ||||
| 			rotateX, _ := floatTextProperty(style, RotateX, session, 1) | ||||
| 			rotateY, _ := floatTextProperty(style, RotateY, session, 1) | ||||
| 			rotateZ, _ := floatTextProperty(style, RotateZ, session, 1) | ||||
| 
 | ||||
| 			if buffer.Len() > 0 { | ||||
| 				buffer.WriteRune(' ') | ||||
| 			} | ||||
| 			buffer.WriteString(`rotate3d(`) | ||||
| 			buffer.WriteString(strconv.FormatFloat(rotateX, 'g', -1, 64)) | ||||
| 			buffer.WriteString(rotateX) | ||||
| 			buffer.WriteRune(',') | ||||
| 			buffer.WriteString(strconv.FormatFloat(rotateY, 'g', -1, 64)) | ||||
| 			buffer.WriteString(rotateY) | ||||
| 			buffer.WriteRune(',') | ||||
| 			buffer.WriteString(strconv.FormatFloat(rotateZ, 'g', -1, 64)) | ||||
| 			buffer.WriteString(rotateZ) | ||||
| 			buffer.WriteRune(',') | ||||
| 			buffer.WriteString(angle.cssString()) | ||||
| 			buffer.WriteRune(')') | ||||
|  | @ -189,14 +178,14 @@ func (style *viewStyle) transform(session Session) string { | |||
| 			buffer.WriteRune(')') | ||||
| 		} | ||||
| 
 | ||||
| 		if scaleOK { | ||||
| 		if okScaleX || okScaleY { | ||||
| 			if buffer.Len() > 0 { | ||||
| 				buffer.WriteRune(' ') | ||||
| 			} | ||||
| 			buffer.WriteString(`scale(`) | ||||
| 			buffer.WriteString(strconv.FormatFloat(scaleX, 'g', -1, 64)) | ||||
| 			buffer.WriteString(scaleX) | ||||
| 			buffer.WriteRune(',') | ||||
| 			buffer.WriteString(strconv.FormatFloat(scaleY, 'g', -1, 64)) | ||||
| 			buffer.WriteString(scaleY) | ||||
| 			buffer.WriteRune(')') | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										15
									
								
								viewUtils.go
								
								
								
								
							
							
						
						
									
										15
									
								
								viewUtils.go
								
								
								
								
							|  | @ -368,7 +368,9 @@ func GetTextWeight(view View, subviewID string) int { | |||
| } | ||||
| 
 | ||||
| // GetTextAlign returns a text align of the subview. Returns one of next values:
 | ||||
| // 	 LeftAlign = 0, RightAlign = 1, CenterAlign = 2, JustifyAlign = 3
 | ||||
| //
 | ||||
| //	LeftAlign = 0, RightAlign = 1, CenterAlign = 2, JustifyAlign = 3
 | ||||
| //
 | ||||
| // If the second argument (subviewID) is "" then a value from the first argument (view) is returned.
 | ||||
| func GetTextAlign(view View, subviewID string) int { | ||||
| 	return enumStyledProperty(view, subviewID, TextAlign, LeftAlign, true) | ||||
|  | @ -601,7 +603,11 @@ func GetScale(view View, subviewID string) (float64, float64, float64) { | |||
| 	if view == nil { | ||||
| 		return 1, 1, 1 | ||||
| 	} | ||||
| 	x, y, z, _ := getScale(view, view.Session()) | ||||
| 
 | ||||
| 	session := view.Session() | ||||
| 	x, _ := floatProperty(view, ScaleX, session, 1) | ||||
| 	y, _ := floatProperty(view, ScaleY, session, 1) | ||||
| 	z, _ := floatProperty(view, ScaleZ, session, 1) | ||||
| 	return x, y, z | ||||
| } | ||||
| 
 | ||||
|  | @ -615,8 +621,11 @@ func GetRotate(view View, subviewID string) (float64, float64, float64, AngleUni | |||
| 		return 0, 0, 0, AngleUnit{Value: 0, Type: Radian} | ||||
| 	} | ||||
| 
 | ||||
| 	session := view.Session() | ||||
| 	angle, _ := angleProperty(view, Rotate, view.Session()) | ||||
| 	rotateX, rotateY, rotateZ := getRotateVector(view, view.Session()) | ||||
| 	rotateX, _ := floatProperty(view, RotateX, session, 1) | ||||
| 	rotateY, _ := floatProperty(view, RotateY, session, 1) | ||||
| 	rotateZ, _ := floatProperty(view, RotateZ, session, 1) | ||||
| 	return rotateX, rotateY, rotateZ, angle | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue