diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md
index e2811f9..2163f2d 100644
--- a/CHANGELOG.en-US.md
+++ b/CHANGELOG.en-US.md
@@ -6,6 +6,7 @@ English (US) release notes, mirroring CHANGELOG.md (Brazilian Portuguese). Befor
### Fixes
- **Xbox controllers no longer ask to be configured** (#284): when an Xbox controller also showed up as a "joystick without a profile" (a second instance, a receiver or a generic driver), the app said "Controle sem perfil… hold any button" and opened the mapping wizard even though the controller already worked. Xbox controllers (Microsoft vendor, or "Xbox"/"XInput" in the name) now never trigger the notice or the wizard; real generic joysticks can still be configured.
### Changes
+- **Landscape Settings, easier to find** (#285, #288, #227): Configurações now uses the screen's width: groups sit side by side in two columns (Exibição and Busca on the left; Controles and ControlFS on the right, in reading order: Down at the end of the first column continues at the top of the second), with the description below and no scrolling at 720p. In a narrow window it goes back to one column. **L1/R1** jump between groups. In the Menu, **Configurações** is now the **first tile** (already focused: Menu + Confirm opens it), with the gear and what's inside. No setting was removed or changed behavior.
- **Controller sounds on by default and nicer** (#286, #287): a fresh install (or no saved choice) now has the sounds on at medium volume; anyone who picked "desligados" (off) stays silent, and the choice is kept across restarts and updates. The four cues were redone: glassy timbre (a fundamental with soft harmonics), rounded attack, gentle decay, all at the same loudness and without clicks; "baixo" (low) is now really low. They are still synthesized in the app (no third-party files; origin and license in THIRD_PARTY_NOTICES.md).
- **Git status left Configurações** (#284): the option, the "Status do Git: ligado/desligado" notice, the branch in the header and the "Git: modificado" marks are gone from the interface.
### What's new
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3db11a2..964aeed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ Notas em português do Brasil; a versão em inglês (Estados Unidos) fica em `CH
### Correções
- **Controle Xbox não pede mais para ser configurado** (#284): quando um controle Xbox aparecia também como "joystick sem perfil" (segunda instância, receptor ou driver genérico), o app avisava "Controle sem perfil… segure qualquer botão" e abria o assistente de configuração, mesmo com o controle já funcionando. Agora controles Xbox (fabricante Microsoft, ou "Xbox"/"XInput" no nome) nunca disparam o aviso nem o assistente; joysticks genéricos de verdade continuam podendo ser configurados.
### Mudanças
+- **Configurações em paisagem e mais fáceis de achar** (#285, #288, #227): as Configurações agora ocupam a largura da tela: os grupos ficam lado a lado em duas colunas (Exibição e Busca à esquerda; Controles e ControlFS à direita, em ordem de leitura: Baixo no fim da primeira coluna continua no topo da segunda), com descrição embaixo, sem rolar em 720p. Em janela estreita voltam a uma coluna. **L1/R1** pulam de um grupo para outro. No Menu, **Configurações** agora é o **primeiro bloco** (já em foco: Menu + Confirmar abre), com a engrenagem e o que tem dentro. Nenhum ajuste foi removido ou mudou de comportamento.
- **Sons do controle ligados por padrão e mais bonitos** (#286, #287): numa instalação nova (ou sem escolha salva) os sons já vêm ligados em volume médio; quem escolheu "desligados" continua sem som, e a escolha fica salva ao reabrir e ao atualizar. Os quatro sons foram refeitos: timbre de vidro (fundamental com harmônicos suaves), ataque arredondado, queda suave, todos com o mesmo volume e sem estalos; o volume "baixo" agora é realmente baixo. Continuam sintetizados no app (sem arquivos de terceiros; a origem e a licença estão em THIRD_PARTY_NOTICES.md).
- **Status do Git saiu das Configurações** (#284): a opção, o aviso "Status do Git: ligado/desligado", o ramo no cabeçalho e as marcas "Git: modificado" deixaram de existir na interface.
### Novidades
diff --git a/docs/ui-redesign.md b/docs/ui-redesign.md
index a5897f3..77e7081 100644
--- a/docs/ui-redesign.md
+++ b/docs/ui-redesign.md
@@ -221,7 +221,7 @@ added line.
| Where | Pickers | Stays one press |
|---|---|---|
| Compactar | Formato, Compressão | Nome (keyboard), Compactar |
-| Configurações | Exibição, Densidade da lista, Tema, Cor de destaque, Ordenar por, Confirmar com, Legendas, Fluidez | Ordem, Painel de detalhes, Itens ocultos, Tela cheia, Busca em subpastas, Recentes, Restaurar abas, Sugestões do teclado, Segundo plano, Mira por giroscópio (on/off or symmetric two-way toggles); Controle ativo, Teste de controles, Controles sem perfil, Atualizações (they open their own screen) |
+| Configurações (paisagem, 2 colunas; L1/R1 pulam de grupo; primeiro bloco do Menu) | Exibição, Densidade da lista, Tema, Cor de destaque, Ordenar por, Confirmar com, Legendas, Fluidez | Ordem, Painel de detalhes, Itens ocultos, Tela cheia, Busca em subpastas, Recentes, Restaurar abas, Sugestões do teclado, Segundo plano, Mira por giroscópio (on/off or symmetric two-way toggles); Controle ativo, Teste de controles, Controles sem perfil, Atualizações (they open their own screen) |
| Filtros da busca | Tamanho, Modificado | Tipos (checkboxes) |
| Renomear em lote | Modo, Converter para | Dígitos (1–6, a stepper), text fields |
diff --git a/src/ControlFS.App/Views/ModalView.cs b/src/ControlFS.App/Views/ModalView.cs
index a57cffc..9902b93 100644
--- a/src/ControlFS.App/Views/ModalView.cs
+++ b/src/ControlFS.App/Views/ModalView.cs
@@ -161,6 +161,9 @@ public static void ScrollBody(int steps)
private static double PanelMargin => Theme.SpaceM;
+ /// Largura mínima do painel (px lógicos) para as Configurações ficarem em duas colunas (#285).
+ private const double MenuTwoColumnMinWidth = 900;
+
///
/// Largura fixa de cada classe de tamanho (#227, px lógicos antes da escala). Nunca depende do conteúdo em foco; a janela
/// (720p, portátil, 4K) sempre limita ().
@@ -171,6 +174,7 @@ public static void ScrollBody(int steps)
ModalSize.Medium => 540,
ModalSize.Standard => 640,
ModalSize.Wide => 960,
+ ModalSize.Landscape => 1080,
_ => double.PositiveInfinity,
};
@@ -607,6 +611,13 @@ private static StackPanel SectionHeading(string? title, bool first)
private static Border BuildMenu(AppController app, MenuModal menu, out Action update)
{
var stack = new StackPanel();
+ // Configurações em paisagem (#285): com largura para isso, os grupos ficam em duas colunas lado a lado (a de baixo
+ // continua a de cima em ordem de leitura). Numa janela estreita, uma coluna só, como sempre.
+ var twoColumns = menu.HasSectionGrids && PanelWidthFor(menu.Size) >= Theme.Scaled(MenuTwoColumnMinWidth);
+ var second = twoColumns ? new StackPanel() : null;
+ var split = twoColumns ? menu.ColumnSplit : int.MaxValue;
+ var target = stack;
+ var owners = new StackPanel[menu.Items.Count];
var hasGrid = menu.Grids.Count > 0;
// Títulos de grupo: em menus só de lista e nas Configurações; com a grade de ações rápidas no topo, só o fio (como o
// menu de contexto do Windows 11).
@@ -616,18 +627,20 @@ private static Border BuildMenu(AppController app, MenuModal menu, out Action up
string? section = null;
for (var i = 0; i < menu.Items.Count;)
{
+ if (i >= split && second is not null && !ReferenceEquals(target, second)) target = second;
var item = menu.Items[i];
var grid = menu.GridOf(i);
// Grupo novo: título (ou só o fio). Menu comum: logo abaixo da grade do topo sempre há o fio separando as duas partes.
var heading = menu.HasSectionGrids || !hasGrid
? (i == 0 ? item.Section is not null : item.Section != section)
: i != 0 && (i == menu.QuickCount || item.Section != section);
- if (heading) stack.Children.Add(SectionHeading(titles || (item.Section is not null && item.Section == menu.TitledSection) ? item.Section : null, first: i == 0));
+ if (heading) target.Children.Add(SectionHeading(titles || (item.Section is not null && item.Section == menu.TitledSection) ? item.Section : null, first: target.Children.Count == 0));
section = item.Section;
if (grid is null)
{
- positions[i] = stack.Children.Count;
- stack.Children.Add(MenuRow(app, menu, i));
+ positions[i] = target.Children.Count;
+ owners[i] = target;
+ target.Children.Add(MenuRow(app, menu, i));
i++;
continue;
}
@@ -635,10 +648,21 @@ private static Border BuildMenu(AppController app, MenuModal menu, out Action up
for (var c = 0; c < grid.Columns; c++) tiles.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
for (var r = 0; r < grid.Rows; r++) tiles.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
for (var t = grid.Start; t < grid.End; t++) tiles.Children.Add(MenuTile(app, menu, t));
- stack.Children.Add(tiles);
+ target.Children.Add(tiles);
grids[grid] = tiles;
i = grid.End;
}
+ UIElement body = stack;
+ if (second is not null)
+ {
+ var columns = new Grid { ColumnSpacing = Theme.SpaceL };
+ columns.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+ columns.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
+ Grid.SetColumn(second, 1);
+ columns.Children.Add(stack);
+ columns.Children.Add(second);
+ body = columns;
+ }
if (menu.Items.Count == 0)
stack.Children.Add(new TextBlock { Text = "Nenhuma opção.", FontSize = Theme.FontBody, Foreground = Theme.TextMuted });
@@ -661,13 +685,13 @@ private static Border BuildMenu(AppController app, MenuModal menu, out Action up
description.Show(menu.Description);
Border? footer = null;
- var card = Panel(app, Header(menu, compact: true), stack, menu.Size, footerSink: f => footer = f, compact: true, below: below);
+ var card = Panel(app, Header(menu, compact: true), body, menu.Size, footerSink: f => footer = f, compact: true, below: below);
var shown = menu.FocusIndex;
void Replace(int index)
{
if (index < 0 || index >= positions.Length) return;
if (menu.GridOf(index) is { } grid) grids[grid].Children[index - grid.Start] = MenuTile(app, menu, index);
- else stack.Children[positions[index]] = MenuRow(app, menu, index);
+ else owners[index].Children[positions[index]] = MenuRow(app, menu, index);
}
update = () =>
{
diff --git a/src/ControlFS.Application/AppController.Browser.cs b/src/ControlFS.Application/AppController.Browser.cs
index 9ff80e2..63014f2 100644
--- a/src/ControlFS.Application/AppController.Browser.cs
+++ b/src/ControlFS.Application/AppController.Browser.cs
@@ -575,6 +575,7 @@ private void ShowAppMenu()
const MenuPlacement quick = MenuPlacement.Quick;
List