diff --git a/CHANGELOG.md b/CHANGELOG.md index f80f85e..4d73377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,15 @@ -# v.11.0 +# v0.12.0 + +* Added SvgImageView + +# v0.11.0 * Added "tabindex", "order", "column-fill", "column-span-all", "background-blend-mode", and "mix-blend-mode" properties * Added GetTabIndex, GetOrder, GetColumnFill, IsColumnSpanAll, GetBackgroundBlendMode, and GetMixBlendMode functions * ClientItem, SetClientItem, and RemoveAllClientItems method added to Session interface * PropertyWithTag method of DataObject interface renamed to PropertyByTag -# v.10.0 +# v0.10.0 * The Canvas.TextWidth method replaced by Canvas.TextMetrics * Added support of WebAssembly diff --git a/README-ru.md b/README-ru.md index c427cad..804d909 100644 --- a/README-ru.md +++ b/README-ru.md @@ -2489,7 +2489,7 @@ ColumnLayout является контейнером, реализующим и "column-count" равно 0 и устанавливает ширину колонки. ВАЖНО! В качестве значения "column-width" нельзя использовать проценты (т.е. если вы зададите -значение в процентах, то это проигнорируется системой) +значение в процентах, то это будет проигнорировано системой) Получить значение данного свойства можно с помощью функции @@ -2943,6 +2943,39 @@ NaturalSize() возвращает исходную ширину и высоту func GetImageViewVerticalAlign(view View, subviewID ...string) int func GetImageViewHorizontalAlign(view View, subviewID ...string) int +## SvgImageView + +Элемент SvgImageView расширяющий интерфейс View предназначен для вывода svg изображений. + +Для создания SvgImageView используется функция: + + func NewSvgImageView(session Session, params Params) ImageView + +Выводимое изображение задается string Свойством "content" (константа Content). +В качестве значения данному свойству может присваиваться +* имя изображения в папке images ресурсов; +* url изображения; +* содержимое svg изображения. + +Примеры + + rui.Set(rootView, "iconView", rui.Content, "icon.svg") + + rui.Set(rootView, "iconView", rui.Content, ` + + + + `) + +Независимо от того как вы определили свойство "content" на клиент всегда передается содержимое svg изображения. Например, если вы задали изображение следующим образом + + rui.Set(rootView, "iconView", rui.Content, "icon.svg") + +то программа сначала загрузит в память содержимое файла "icon.svg", +а затем передаст клиенту это содержимое в качестве значения свойства "content". + +Это позволяет включать svg изображения в ресурсы WebAssembly приложения. + ## EditView Элемент EditView является редактором теста и расширяет интерфейс View. diff --git a/README.md b/README.md index 8f8fae6..8a8bb99 100644 --- a/README.md +++ b/README.md @@ -2914,6 +2914,39 @@ The following functions can be used to retrieve ImageView property values: func GetImageViewVerticalAlign(view View, subviewID ...string) int func GetImageViewHorizontalAlign(view View, subviewID ...string) int +## SvgImageView + +The SvgImageView element extending the View interface is designed to display svg images. + +To create an SvgImageView function is used: + + func NewSvgImageView(session Session, params Params) ImageView + +The image to be displayed is specified by the string property "content" (constant Content). +The value of this property can be assigned +* the image file name in the images folder of the resources; +* image url; +* content of the svg image. + +Examples + + rui.Set(rootView, "iconView", rui.Content, "icon.svg") + + rui.Set(rootView, "iconView", rui.Content, ` + + + + `) + +Regardless of how you determined the property of "Content" to the client is always transmitted the contents of the SVG image. For example, if you set the image as follows + + rui.Set(rootView, "iconView", rui.Content, "icon.svg") + +then the program will first upload the contents of the "icon.svg" file to the memory, +and then transmit this contents to the client as the value of the "content" property. + +This allows you to include SVG images in the resources of a WebAssembly application. + ## EditView The EditView element is a test editor and extends the View interface. diff --git a/app_styles.css b/app_styles.css index cf66269..32c37e3 100644 --- a/app_styles.css +++ b/app_styles.css @@ -115,13 +115,14 @@ ul:focus { display: grid; } +.ruiSvgImageView { + display: grid; +} + .ruiListView { overflow: auto; - /* - display: flex; - align-content: stretch; - */ } + /* @media (prefers-color-scheme: light) { body { diff --git a/application.go b/application.go index 0e45e0a..6b0cb19 100644 --- a/application.go +++ b/application.go @@ -77,7 +77,7 @@ func getStartPage(buffer *strings.Builder, params AppParams, addScripts string)
- + `) } diff --git a/svgImageView.go b/svgImageView.go new file mode 100644 index 0000000..ed49fa9 --- /dev/null +++ b/svgImageView.go @@ -0,0 +1,147 @@ +package rui + +import ( + "io" + "net/http" + "strings" +) + +// SvgImageView - image View +type SvgImageView interface { + View +} + +type svgImageViewData struct { + viewData +} + +// NewSvgImageView create new SvgImageView object and return it +func NewSvgImageView(session Session, params Params) SvgImageView { + view := new(svgImageViewData) + view.init(session) + setInitParams(view, params) + return view +} + +func newSvgImageView(session Session) View { + return NewSvgImageView(session, nil) +} + +// Init initialize fields of imageView by default values +func (imageView *svgImageViewData) init(session Session) { + imageView.viewData.init(session) + imageView.tag = "SvgImageView" + imageView.systemClass = "ruiSvgImageView" +} + +func (imageView *svgImageViewData) String() string { + return getViewString(imageView) +} + +func (imageView *svgImageViewData) normalizeTag(tag string) string { + tag = strings.ToLower(tag) + switch tag { + case Source, "source": + tag = Content + + case VerticalAlign: + tag = CellVerticalAlign + + case HorizontalAlign: + tag = CellHorizontalAlign + } + return tag +} + +func (imageView *svgImageViewData) Remove(tag string) { + imageView.remove(imageView.normalizeTag(tag)) +} + +func (imageView *svgImageViewData) remove(tag string) { + imageView.viewData.remove(tag) + + if imageView.created { + switch tag { + case Content: + updateInnerHTML(imageView.htmlID(), imageView.session) + } + } +} + +func (imageView *svgImageViewData) Set(tag string, value any) bool { + return imageView.set(imageView.normalizeTag(tag), value) +} + +func (imageView *svgImageViewData) set(tag string, value any) bool { + if value == nil { + imageView.remove(tag) + return true + } + + switch tag { + case Content: + if text, ok := value.(string); ok { + imageView.properties[Content] = text + if imageView.created { + updateInnerHTML(imageView.htmlID(), imageView.session) + } + imageView.propertyChangedEvent(Content) + return true + } + notCompatibleType(Source, value) + return false + + default: + return imageView.viewData.set(tag, value) + } +} + +func (imageView *svgImageViewData) Get(tag string) any { + return imageView.viewData.get(imageView.normalizeTag(tag)) +} + +func (imageView *svgImageViewData) htmlTag() string { + return "div" +} + +func (imageView *svgImageViewData) htmlSubviews(self View, buffer *strings.Builder) { + if value := imageView.getRaw(Content); value != nil { + if content, ok := value.(string); ok && content != "" { + if image, ok := resources.images[content]; ok && image.fs != nil { + if data, err := image.fs.ReadFile(image.path); err == nil { + buffer.WriteString(string(data)) + return + } else { + DebugLog(err.Error()) + } + } + + if strings.HasPrefix(content, "http://") || strings.HasPrefix(content, "https://") { + resp, err := http.Get(content) + if err == nil { + defer resp.Body.Close() + if body, err := io.ReadAll(resp.Body); err == nil { + buffer.WriteString(string(body)) + return + } + } + + DebugLog(err.Error()) + } + + buffer.WriteString(content) + } + } +} + +// GetSvgImageViewVerticalAlign return the vertical align of an SvgImageView subview: TopAlign (0), BottomAlign (1), CenterAlign (2) +// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned +func GetSvgImageViewVerticalAlign(view View, subviewID ...string) int { + return enumStyledProperty(view, subviewID, CellVerticalAlign, LeftAlign, false) +} + +// GetSvgImageViewHorizontalAlign return the vertical align of an SvgImageView subview: LeftAlign (0), RightAlign (1), CenterAlign (2) +// If the second argument (subviewID) is not specified or it is "" then a left position of the first argument (view) is returned +func GetSvgImageViewHorizontalAlign(view View, subviewID ...string) int { + return enumStyledProperty(view, subviewID, CellHorizontalAlign, LeftAlign, false) +} diff --git a/viewFactory.go b/viewFactory.go index 0ee7778..5e2b9ec 100644 --- a/viewFactory.go +++ b/viewFactory.go @@ -30,6 +30,7 @@ var viewCreators = map[string]func(Session) View{ "ListView": newListView, "CanvasView": newCanvasView, "ImageView": newImageView, + "SvgImageView": newSvgImageView, "TableView": newTableView, "AudioPlayer": newAudioPlayer, "VideoPlayer": newVideoPlayer,