001package polaris.sdk.ui.samples; 002 003import polaris.sdk.ui.*; 004import polaris.sdk.ui.controls.*; 005import static polaris.sdk.ui.samples.SceneSupport.*; 006 007/** A practical settings form. Palette changes are real; account/preferences are session-local. */ 008public final class SettingsScene extends SceneSupport.AppScene { 009 private final Panel identity=new Panel(),preferences=new Panel();private final Avatar avatar=new Avatar("访客"); 010 private final Label accountName=title("Glass User"),saved=caption("尚未应用修改"),help=caption("外观设置作用于本窗口;账户与通知设置仅在此示例内保存。"); 011 private final TextField nickname=new TextField("Glass User"),signature=new TextField("让界面保持轻盈。"); 012 private final Switch notifications=new Switch("允许示例通知"),sounds=new Switch("消息声音选项(模拟)"),reduceMotion=new Switch("减少动态效果"); 013 private final ButtonGroup appearance=new ButtonGroup("深色","浅色");private final ColorPicker accent=new ColorPicker(); 014 private final Slider fontSize=new Slider();private final Label fontLabel=caption("字号 14 px");private final ComboSelect language=new ComboSelect("简体中文","English · 仅记录选项"); 015 private final Button apply=new Button("应用设置").primary(true),undo=new Button("撤销未应用修改"),test=new Button("发送测试通知"); 016 private String savedName="Glass User",savedSignature="让界面保持轻盈。";private boolean savedNotify=true,savedSound;private int savedLanguage;private Theme savedTheme; 017 private boolean ready;private int applied; 018 public SettingsScene(){super("偏好设置","系统设置 / 账户表单、主题切换、配色、字号、开关与应用反馈");id("scene.settings"); 019 mount(this,identity,"settings.identity");mount(this,preferences,"settings.preferences");mount(this,help,null); 020 mount(identity,avatar,null);mount(identity,accountName,"settings.accountName");mount(identity,caption("本地演示账户"),"settings.local"); 021 mount(identity,caption("显示名称"),"settings.nameLabel");mount(identity,nickname,"settings.nickname");nickname.maxLength(24);nickname.onChange(v->{accountName.text(nickname.value().trim().isEmpty()?"未命名":nickname.value());avatar.text(nickname.value().trim().isEmpty()?"?":nickname.value());}); 022 mount(identity,caption("个人签名"),"settings.signatureLabel");mount(identity,signature,"settings.signature");signature.maxLength(60); 023 mount(identity,caption("语言偏好 · 仅保存,不切换翻译"),"settings.languageLabel");mount(identity,language,"settings.language");mount(identity,saved,"settings.saved"); 024 mount(preferences,title("外观与交互"),"settings.appearanceTitle");mount(preferences,appearance,"settings.appearance");appearance.select(0);appearance.onChange(v->{if(ready)changeAppearance(appearance.selectedIndex()==0);}); 025 mount(preferences,caption("强调色"),"settings.accentLabel");mount(preferences,accent,"settings.accent");accent.color(0xffe6e6e6);accent.onChange(v->{if(ui!=null){ui.theme().accent(accent.color());float r=((accent.color()>>16)&255),g=((accent.color()>>8)&255),b=accent.color()&255;ui.theme().accentText(r*.2126f+g*.7152f+b*.0722f>150?0xff151515:0xfff5f5f5);}}); 026 mount(preferences,fontLabel,"settings.fontLabel");mount(preferences,fontSize,"settings.fontSize");fontSize.range(11,19).value(14);fontSize.onChange(v->{fontLabel.text("字号 "+Math.round(fontSize.value())+" px");if(ui!=null)ui.theme().fontSize=(float)fontSize.value();}); 027 mount(preferences,reduceMotion,"settings.reducedMotion");reduceMotion.onChange(v->{if(ui!=null)ui.theme().reducedMotion=reduceMotion.selected();}); 028 mount(preferences,notifications,"settings.notifications");notifications.selected(true);mount(preferences,sounds,"settings.sounds"); 029 mount(preferences,test,"settings.test");test.onClick(v->{if(notifications.selected())notice(this,"示例通知","偏好设置已经连接到实际通知组件。");else saved.text("示例通知已关闭,未发送通知。");}); 030 mount(preferences,apply,"settings.apply");apply.onClick(v->apply());mount(preferences,undo,"settings.undo");undo.onClick(v->undo()); 031 } 032 @Override public void attach(Ui context){super.attach(context);if(context!=null&&!ready){savedTheme=context.theme().copy();syncTheme();ready=true;}} 033 public int applyCount(){return applied;} 034 public String savedName(){return savedName;} 035 public void apply(){if(nickname.value().trim().isEmpty()){saved.text("名称不能为空。");return;} 036 savedName=nickname.value().trim();savedSignature=signature.value();savedNotify=notifications.selected();savedSound=sounds.selected();savedLanguage=language.selectedIndex();if(ui!=null)savedTheme=ui.theme().copy();applied++;saved.text("已应用第 "+applied+" 次修改 · 当前窗口有效"); 037 } 038 public void undo(){nickname.value(savedName);signature.value(savedSignature);notifications.selected(savedNotify);sounds.selected(savedSound);language.select(savedLanguage);accountName.text(savedName);avatar.text(savedName);if(ui!=null&&savedTheme!=null)ui.theme(savedTheme.copy());syncTheme();saved.text("已恢复上次应用的设置。");} 039 private void syncTheme(){if(ui==null)return;boolean was=ready;ready=false;appearance.select(ui.theme().dark?0:1);accent.color(ui.theme().accent);fontSize.value(ui.theme().fontSize);reduceMotion.selected(ui.theme().reducedMotion);fontLabel.text("字号 "+Math.round(ui.theme().fontSize)+" px");ready=was;} 040 private void changeAppearance(boolean dark){if(ui==null)return;Theme t=ui.theme().copy(),p=dark?Theme.dark():Theme.light();t.dark=dark;t.text=p.text;t.muted=p.muted;t.surface=p.surface;t.field=p.field;t.border=p.border;t.selected=p.selected;t.accent=p.accent;t.accentText=p.accentText;t.background=p.background;t.backgroundAccent=p.backgroundAccent;t.disabledText=p.disabledText;t.shade=p.shade;t.highlight=p.highlight;t.shadow=p.shadow;ui.theme(t);accent.color(t.accent);} 041 @Override public float preferredHeight(float width){return width<760?1070:592;} 042 @Override protected void layoutChildren(){header();boolean stacked=w<760;float iw=stacked?w:Math.min(350,w*.4f),pw=stacked?w:w-iw-GAP; 043 place(identity,0,76,iw,466);place(preferences,stacked?0:iw+GAP,stacked?554:76,pw,466); 044 place(avatar,16,16,52,52);place(accountName,80,20,iw-96,28);place(find("settings.local"),80,51,iw-96,22); 045 place(find("settings.nameLabel"),16,99,iw-32,22);place(nickname,16,131,iw-32,38);place(find("settings.signatureLabel"),16,185,iw-32,22);place(signature,16,217,iw-32,38); 046 place(find("settings.languageLabel"),16,275,iw-32,22);place(language,16,307,iw-32,38);place(saved,16,390,iw-32,45); 047 place(find("settings.appearanceTitle"),16,16,pw-32,28);place(appearance,16,59,pw-32,38);place(find("settings.accentLabel"),16,117,100,22);place(accent,128,109,pw-144,36); 048 place(fontLabel,16,165,140,22);place(fontSize,163,155,pw-179,32);place(reduceMotion,16,205,pw-32,32);place(notifications,16,249,pw-32,32);place(sounds,16,293,pw-32,32); 049 place(test,16,337,pw-32,34);place(undo,16,401,(pw-44)/2,40);place(apply,28+(pw-44)/2,401,(pw-44)/2,40); 050 float bottom=Math.max(identity.y()+identity.height(),preferences.y()+preferences.height());place(help,0,bottom+16,w,28);h=bottom+50; 051 } 052}