blob: 65ba2f9c158ce357c46f13d6a60976c3cc449490 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package client
import (
"fmt"
"android.googlesource.com/platform/tools/gpu/atom"
"android.googlesource.com/platform/tools/gpu/_experimental/client/schema"
"android.googlesource.com/platform/tools/gpu/memory"
"github.com/google/gxui"
"github.com/google/gxui/math"
)
const kStateAdapterItemHeight = 18
func createControls(appCtx *ApplicationContext, name string, value interface{}) gxui.Control {
theme := appCtx.Theme()
layout := theme.CreateLinearLayout()
layout.SetDirection(gxui.LeftToRight)
addLabel := func(format string, args ...interface{}) {
label := theme.CreateLabel()
label.SetText(fmt.Sprintf(format, args...))
label.SetMargin(math.ZeroSpacing)
label.SetMultiline(false)
layout.AddChild(label)
}
addButton := func(format string, args ...interface{}) gxui.Button {
button := theme.CreateButton()
button.SetText(fmt.Sprintf(format, args...))
// button.SetPadding(math.ZeroSpacing)
button.SetMargin(math.ZeroSpacing)
layout.AddChild(button)
return button
}
addLabel("%s: ", name)
switch ty := value.(type) {
case atom.ID:
addButton(fmt.Sprintf("0x%.8x", ty)).OnClick(func(gxui.MouseEvent) {
appCtx.SelectAtom(ty)
})
case memory.Pointer:
addButton(fmt.Sprintf("0x%.8x", ty)).OnClick(func(gxui.MouseEvent) {
appCtx.SelectAddress(ty)
})
case schema.EnumValue:
addLabel(fmt.Sprintf("%v", ty))
case string, int, uint, int32, uint32, int16, uint16, int8, uint8, float32, float64, bool:
// TODO: Click to select object
// obj := state.LookupId(ty)
// addButton(ty.String()).OnClick(func(gxui.MouseEvent) {
// appCtx.SelectObject(obj)
// })
addLabel(fmt.Sprintf("%v", ty))
}
return layout
}
type StateAdapterItem struct {
appCtx *ApplicationContext
key string
value interface{}
children []*StateAdapterItem
}
func (i *StateAdapterItem) Init(appCtx *ApplicationContext, key string, value interface{}) {
i.appCtx = appCtx
i.key = key
i.value = value
switch ty := value.(type) {
case schema.Struct:
for _, f := range ty.Fields {
child := &StateAdapterItem{}
child.Init(appCtx, f.Info.Name, f.Value)
i.children = append(i.children, child)
}
case schema.Class:
for _, f := range ty.Fields {
child := &StateAdapterItem{}
child.Init(appCtx, f.Info.Name, f.Value)
i.children = append(i.children, child)
}
case schema.Array:
for k, e := range ty.Elements {
child := &StateAdapterItem{}
child.Init(appCtx, fmt.Sprintf("%d", k), e)
i.children = append(i.children, child)
}
case schema.Map:
for _, e := range ty.Elements {
child := &StateAdapterItem{}
child.Init(appCtx, fmt.Sprintf("%v", e.Key), e.Value)
i.children = append(i.children, child)
}
}
}
func (i *StateAdapterItem) Count() int {
return len(i.children)
}
func (i *StateAdapterItem) NodeAt(index int) gxui.TreeNode {
if len(i.children[index].children) > 0 {
return i.children[index]
} else {
return nil
}
}
func (i *StateAdapterItem) ItemAt(index int) gxui.AdapterItem {
return i.children[index]
}
func (i *StateAdapterItem) ItemIndex(item gxui.AdapterItem) int {
// Brute force search
sai := item.(*StateAdapterItem)
for i, c := range i.children {
if c == sai {
return i
}
if idx := c.ItemIndex(item); idx >= 0 {
return i
}
}
return -1
}
func (i *StateAdapterItem) Create(t gxui.Theme, index int) gxui.Control {
return createControls(i.appCtx, i.children[index].key, i.children[index].value)
}
type StateAdapter struct {
StateAdapterItem
gxui.AdapterBase
}
func CreateStateAdapter(appCtx *ApplicationContext, state schema.Struct) *StateAdapter {
adapter := &StateAdapter{}
adapter.Init(appCtx, "state", state)
return adapter
}
func (r *StateAdapter) Size(theme gxui.Theme) math.Size {
return math.Size{W: math.MaxSize.W, H: kStateAdapterItemHeight}
}