LevelOS-Core/UI/Dashboards/Cadastros/OrdensCadastroPanel.cs

957 lines
37 KiB
C#

using CPM;
using CustomMessageBox;
using System;
using System.Drawing;
using System.Windows.Forms;
// Atalhos estáticos — eliminam o prefixo "ScreenProfile." em todo o arquivo
using static UI.ScreenProfile;
namespace UI
{
public class OrdensCadastroPanel : FormularioModelo
{
#region Campos
private Label lblNumeroOS = null!;
private Panel cardCliente = null!;
private Panel cardDatas = null!;
private Panel cardFinanceiro = null!;
private Panel cardRodape = null!;
private TabControl tabDetalhes = null!;
private LV_TEXTBOX1 txtCliente = null!;
private LV_TEXTBOX1 txtEndereco = null!;
private LV_TEXTBOX1 txtTelefones = null!;
private LV_TEXTBOX1 txtDocs = null!;
private LV_TEXTBOX1 txtEmail = null!;
private LV_TEXTBOX1 txtGarantia = null!;
private LV_TEXTBOX1 txtAdiantamento = null!;
private LV_TEXTBOX1 txtMaoObra = null!;
private LV_TEXTBOX1 txtPecas = null!;
private LV_TEXTBOX1 txtDeslocamento = null!;
private LV_TEXTBOX1 txtServicosTerceiros = null!;
private LV_TEXTBOX1 txtOutros = null!;
private LV_TEXTBOX1 txtTotal = null!;
private DateTimePicker dtpEntrada = null!;
private DateTimePicker dtpPronto = null!;
private DateTimePicker dtpSaida = null!;
private DateTimePicker dtpGarantia = null!;
private ComboBox cbSituacao = null!;
private ComboBox cbTecnico = null!;
private ComboBox cbPrioridade = null!;
#endregion
// ══════════════════════════════════════════════════════════════
// Layout base: desenhado para 1920x1080 @ 96 DPI (Scale = 1.0)
// Tudo que está em pixels aqui é o valor ANTES da escala.
// Use sempre S(), P(), Sz(), R(), F() para aplicar o Scale.
// ══════════════════════════════════════════════════════════════
public OrdensCadastroPanel()
{
Titulo = "Ordem de Serviço";
content.Width = S(1180);
content.Height = S(870);
content.BackColor = Color.FromArgb(245, 247, 250);
BuildInterface();
#if DEBUG
if (ParentForm != null)
ParentForm.Text += $" [{ScreenProfile.Diagnostico()}]";
#endif
}
#region Build
private void BuildInterface()
{
BuildHeader();
BuildCliente();
BuildDatasStatus();
BuildFinanceiro();
BuildTabs();
BuildRodape();
}
// Card interno (com borda simples, sem sombra)
private Panel CreateInternalCard(string title, Rectangle rect)
{
var pnl = new Panel
{
Location = rect.Location,
Size = rect.Size,
BackColor = Color.White,
BorderStyle = BorderStyle.FixedSingle
};
var lbl = new Label
{
Text = title,
Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold),
ForeColor = AccentBlue,
Location = P(8, 6),
AutoSize = true
};
pnl.Controls.Add(lbl);
return pnl;
}
#endregion
// ──────────────────────────────────────────────────────────────
// HEADER (y=10, h=60)
// ──────────────────────────────────────────────────────────────
#region Header
private void BuildHeader()
{
var header = new Panel
{
Location = P(10, 10),
Size = Sz(1160, 60),
BackColor = Color.White
};
header.Paint += CardPaint;
lblNumeroOS = new Label
{
Text = "O.S. nº 1771",
Font = new Font("Segoe UI", F(20f), FontStyle.Bold),
ForeColor = Color.FromArgb(210, 38, 38),
Location = P(12, 8),
AutoSize = true
};
var lblSub = new Label
{
Text = "Cadastro e gerenciamento da ordem de serviço",
Font = new Font("Segoe UI", F(8f)),
ForeColor = Color.Gray,
Location = P(15, 42),
AutoSize = true
};
header.Controls.Add(lblNumeroOS);
header.Controls.Add(lblSub);
content.Controls.Add(header);
}
#endregion
// ──────────────────────────────────────────────────────────────
// CLIENTE (y=80, h=160)
// ──────────────────────────────────────────────────────────────
#region Cliente
private void BuildCliente()
{
cardCliente = CreateCard(R(10, 80, 850, 170), "Dados do Cliente");
// Calcula tudo em pixels JA ESCALADOS para evitar dupla escala
int m = S(12);
int iw = cardCliente.Width - m * 2;
int gap = S(8);
int col = (iw - gap * 2) / 3;
int h26 = S(26);
int h16 = S(16);
int y1 = S(35);
int y2 = S(80);
int y3 = S(125);
// Helper local: coordenadas ja em pixels escalados
LV_TEXTBOX1 Inp(Control p, string lbl, int x, int y, int w)
{
p.Controls.Add(new Label
{
Text = lbl,
Font = new Font("Segoe UI", F(8f), FontStyle.Bold),
ForeColor = TextDark,
Location = new Point(x, y),
AutoSize = true
});
var tb = new LV_TEXTBOX1
{
Location = new Point(x, y + h16),
Size = new Size(w, h26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue,
BackColor = Color.White
};
p.Controls.Add(tb);
return tb;
}
txtCliente = Inp(cardCliente, "Cliente", m, y1, iw);
txtEndereco = Inp(cardCliente, "Endereço", m, y2, iw);
txtTelefones = Inp(cardCliente, "Telefones", m, y3, col);
txtDocs = Inp(cardCliente, "Documentos", m + col + gap, y3, col);
txtEmail = Inp(cardCliente, "E-mail", m + (col + gap) * 2, y3, iw - (col + gap) * 2);
content.Controls.Add(cardCliente);
txtCliente.Text = "Nicolas Felipe G. dos santos";
}
#endregion
// ──────────────────────────────────────────────────────────────
// STATUS E DATAS (y=248, h=130)
// ──────────────────────────────────────────────────────────────
#region Datas
private void BuildDatasStatus()
{
cardDatas = CreateCard(R(10, 248, 850, 130), "Status e Datas");
// Linha 1
AddSmallLabel(cardDatas, "Entrada", 12, 35);
dtpEntrada = CreatePicker(12, 52, 175);
cardDatas.Controls.Add(dtpEntrada);
AddSmallLabel(cardDatas, "Saída", 200, 35);
dtpSaida = CreatePicker(200, 52, 175);
cardDatas.Controls.Add(dtpSaida);
cbSituacao = AddComboBox(cardDatas, "Situação da OS", 390, 35, 445);
// Linha 2
AddSmallLabel(cardDatas, "Pronto", 12, 85);
dtpPronto = CreatePicker(12, 102, 175);
cardDatas.Controls.Add(dtpPronto);
AddSmallLabel(cardDatas, "Garantia até", 200, 85);
dtpGarantia = CreatePicker(200, 102, 175);
cardDatas.Controls.Add(dtpGarantia);
var btnHistorico = new Button
{
Text = "🕘 Histórico",
Location = P(390, 97),
Size = Sz(210, 28),
FlatStyle = FlatStyle.Flat,
BackColor = Color.White,
ForeColor = TextDark,
Font = new Font("Segoe UI Semibold", F(8.5f)),
Cursor = Cursors.Hand
};
btnHistorico.FlatAppearance.BorderColor = BorderColor;
btnHistorico.FlatAppearance.MouseOverBackColor = Color.FromArgb(235, 240, 255);
btnHistorico.Click += (s, e) =>
MessageBox.Show("Abrir histórico da OS", "Histórico",
MessageBoxButtons.OK, MessageBoxIcon.Information);
cardDatas.Controls.Add(btnHistorico);
content.Controls.Add(cardDatas);
}
#endregion
// ──────────────────────────────────────────────────────────────
// FINANCEIRO (x=870, y=80, w=300, h=298)
// — alinhado com Cliente + Datas somados
// ──────────────────────────────────────────────────────────────
#region Financeiro
private void BuildFinanceiro()
{
// altura = 160(cliente) + 8(gap) + 130(datas) = 298
cardFinanceiro = CreateCard(R(870, 80, 300, 298), "Financeiro");
int y = 35;
int step = 34; // espaço entre linhas — compacto
txtAdiantamento = AddFinanceRow(cardFinanceiro, "Adiantamento", y); y += step;
txtMaoObra = AddFinanceRow(cardFinanceiro, "Mão-de-obra", y); y += step;
txtPecas = AddFinanceRow(cardFinanceiro, "Peças", y); y += step;
txtDeslocamento = AddFinanceRow(cardFinanceiro, "Deslocamento", y); y += step;
txtServicosTerceiros = AddFinanceRow(cardFinanceiro, "Serv. terceiros", y); y += step;
txtOutros = AddFinanceRow(cardFinanceiro, "Outros", y); y += step + 8;
var line = new Panel
{
BackColor = BorderColor,
Location = P(10, y),
Size = Sz(278, 1)
};
cardFinanceiro.Controls.Add(line);
y += 10;
var lblTotal = new Label
{
Text = "TOTAL",
Font = new Font("Segoe UI", F(10f), FontStyle.Bold),
ForeColor = Color.FromArgb(220, 38, 38),
Location = P(12, y + 6),
AutoSize = true
};
txtTotal = new LV_TEXTBOX1
{
Location = P(110, y),
Size = Sz(168, 32),
Font = new Font("Segoe UI", F(12f), FontStyle.Bold),
TextAlign = HorizontalAlignment.Right,
BorderColor = Color.FromArgb(220, 38, 38),
BorderFocusColor = Color.FromArgb(220, 38, 38),
ForeColor = Color.FromArgb(220, 38, 38)
};
cardFinanceiro.Controls.Add(lblTotal);
cardFinanceiro.Controls.Add(txtTotal);
content.Controls.Add(cardFinanceiro);
}
#endregion
// ──────────────────────────────────────────────────────────────
// TABS (y=386, h=420)
// ──────────────────────────────────────────────────────────────
#region Tabs
private void BuildTabs()
{
tabDetalhes = new TabControl
{
Location = P(10, 386),
Size = Sz(1160, 430),
Font = new Font("Segoe UI", F(8.5f)),
DrawMode = TabDrawMode.OwnerDrawFixed,
SizeMode = TabSizeMode.Fixed,
ItemSize = Sz(170, 30)
};
tabDetalhes.DrawItem += DrawTab;
BuildTabAparelho();
BuildTabServicos();
BuildTabPecas();
BuildTabLaudo();
BuildTabMiscelanea();
content.Controls.Add(tabDetalhes);
}
// ── Aparelho ─────────────────────────────────────────────────
private void BuildTabAparelho()
{
var tab = new TabPage("Aparelho") { BackColor = Color.White };
AddModernInput(tab, "Modelo", 12, 12, 490);
AddModernInput(tab, "Marca", 520, 12, 490);
AddModernInput(tab, "Operadora", 12, 70, 280);
AddModernInput(tab, "Serial", 310, 70, 280);
AddModernInput(tab, "Nº Patrimônio", 608, 70, 402);
var txtAcessorios = AddModernInput(tab, "Acessórios", 12, 128, 490, 80);
txtAcessorios.Multiline = true;
var txtDefeito = AddModernInput(tab, "Defeito / Reclamação", 520, 128, 490, 80);
txtDefeito.Multiline = true;
tabDetalhes.TabPages.Add(tab);
}
// ── Mão de obra / Serviços ───────────────────────────────────
private void BuildTabServicos()
{
var tab = new TabPage("Mão de obra / Serviços") { BackColor = Color.White };
tab.Controls.Add(new Label
{
Text = "Serviços executados nesta OS",
Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(12, 10),
AutoSize = true
});
var grid = CriarGrid(P(12, 30), Sz(940, 230));
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Descrição", Width = S(310) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Tipo", Width = S(80) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Início", Width = S(70) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Fim", Width = S(70) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Qtd", Width = S(55) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor", Width = S(90) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", Width = S(290) });
tab.Controls.Add(grid);
// menu lateral
var pnl = new Panel { Location = P(962, 30), Size = Sz(170, 230), BackColor = Color.White };
pnl.Controls.Add(BotaoLateral("Padrões", 0, AccentBlue, (s, e) =>
NT_MessageBox.Show("Testando evento click padrão", "Padrão",
MessageBoxButtons.OK, MessageBoxIcon.Information)));
pnl.Controls.Add(BotaoLateral("Avulsos", 44, Color.FromArgb(34, 197, 94)));
pnl.Controls.Add(BotaoLateral("Excluir", 88, Color.FromArgb(239, 68, 68)));
pnl.Controls.Add(new Label
{
Text = "Total horas",
Font = new Font("Segoe UI", F(8f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(8, 130),
AutoSize = true
});
pnl.Controls.Add(new LV_TEXTBOX1
{
Location = P(8, 146),
Size = Sz(148, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue,
Font = new Font("Segoe UI", F(9f), FontStyle.Bold)
});
pnl.Controls.Add(new Label
{
Text = "Total",
Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold),
ForeColor = Color.Red,
Location = P(8, 175),
AutoSize = true
});
pnl.Controls.Add(new LV_TEXTBOX1
{
Location = P(8, 193),
Size = Sz(148, 28),
BorderColor = Color.Red,
BorderFocusColor = Color.Red,
Font = new Font("Segoe UI", F(10f), FontStyle.Bold),
ForeColor = Color.Red
});
tab.Controls.Add(pnl);
// observações
tab.Controls.Add(new Label
{
Text = "Observações internas",
Font = new Font("Segoe UI", F(8f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(12, 272),
AutoSize = true
});
tab.Controls.Add(new LV_TEXTBOX1
{
Location = P(12, 288),
Size = Sz(940, 80),
Multiline = true,
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
tab.Controls.Add(BotaoLateral("Deslocamentos", 288, AccentBlue,
location: P(962, 288), size: Sz(148, 32)));
tabDetalhes.TabPages.Add(tab);
}
// ── Peças utilizadas ─────────────────────────────────────────
private void BuildTabPecas()
{
var tab = new TabPage("Peças utilizadas") { BackColor = Color.White };
tab.Controls.Add(new Label
{
Text = "Peças utilizadas nesta OS",
Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(12, 10),
AutoSize = true
});
var grid = CriarGrid(P(12, 30), Sz(940, 340));
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Peça nº", Width = S(115) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Descrição", Width = S(295) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor un", Width = S(105) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Qtd.", Width = S(75) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor Total", Width = S(115) });
grid.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", Width = S(190) });
tab.Controls.Add(grid);
var pnl = new Panel { Location = P(962, 30), Size = Sz(170, 340), BackColor = Color.White };
pnl.Controls.Add(BotaoLateral("Peças do Estoque", 0, AccentBlue));
pnl.Controls.Add(BotaoLateral("Peças avulsas", 44, Color.FromArgb(34, 197, 94)));
pnl.Controls.Add(BotaoLateral("KIT Montado", 88, Color.FromArgb(245, 158, 11)));
pnl.Controls.Add(BotaoLateral("Excluir", 132, Color.FromArgb(239, 68, 68)));
pnl.Controls.Add(BotaoLateral("Inserir orçamento", 176, Color.FromArgb(99, 102, 241)));
pnl.Controls.Add(BotaoLateral("Requisição", 220, Color.FromArgb(107, 114, 128)));
tab.Controls.Add(pnl);
tabDetalhes.TabPages.Add(tab);
}
// ── Laudo técnico ────────────────────────────────────────────
private void BuildTabLaudo()
{
var tab = new TabPage("Obs / Laudo técnico") { BackColor = Color.White };
tab.Controls.Add(new Label
{
Text = "Laudo técnico / detalhes do conserto",
Font = new Font("Segoe UI", F(8.5f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(12, 10),
AutoSize = true
});
tab.Controls.Add(new Label
{
Text = "(SHIFT + Enter para nova linha)",
Font = new Font("Segoe UI", F(7.5f)),
ForeColor = Color.Gray,
Location = P(820, 12),
AutoSize = true
});
var txtLaudo = new LV_TEXTBOX1
{
Location = P(12, 30),
Size = Sz(1118, 330),
Multiline = true,
BorderColor = BorderColor,
BorderFocusColor = AccentBlue,
Font = new Font("Segoe UI", F(9f)),
BackColor = Color.White
};
tab.Controls.Add(txtLaudo);
var btnPreencher = new Button
{
Text = "📝 Preencher Laudo",
Location = P(12, 372),
Size = Sz(165, 32),
FlatStyle = FlatStyle.Flat,
BackColor = AccentBlue,
ForeColor = Color.White,
Font = new Font("Segoe UI Semibold", F(8.5f)),
Cursor = Cursors.Hand
};
btnPreencher.FlatAppearance.BorderSize = 0;
btnPreencher.Click += (s, e) =>
{
txtLaudo.Text =
"Equipamento analisado e testado em bancada.\r\n\r\n" +
"Foi identificado defeito no componente principal.\r\n\r\n" +
"Realizado:\r\n- limpeza interna\r\n- substituição de peças\r\n- testes finais\r\n\r\n" +
"Equipamento funcionando normalmente.";
};
tab.Controls.Add(btnPreencher);
tabDetalhes.TabPages.Add(tab);
}
// ── Miscelânea ───────────────────────────────────────────────
private void BuildTabMiscelanea()
{
var tab = new TabPage("Miscelânea") { BackColor = Color.White };
// ── Card Garantia (x=10, y=10, w=640, h=260)
var cardGarantia = CreateInternalCard("Garantia / Garantidor", R(10, 10, 640, 260));
var cbGarantidor = AddComboBox(cardGarantia, "Fábrica / Garantidor", 10, 22, 290);
cbGarantidor.Items.AddRange(new object[] { "Nenhum", "Samsung", "LG", "Motorola", "Dell" });
cbGarantidor.SelectedIndex = 0;
AddSmallLabel(cardGarantia, "Senha garantidor", 10, 68);
cardGarantia.Controls.Add(new LV_TEXTBOX1
{
Location = P(10, 84),
Size = Sz(210, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
cardGarantia.Controls.Add(new Label
{
Text = "A fábrica/Garantidor é aquele que pagará pelo reparo.",
Font = new Font("Segoe UI", F(7.5f)),
ForeColor = Color.FromArgb(120, 53, 15),
BackColor = Color.FromArgb(254, 249, 195),
Location = P(235, 84),
Size = Sz(385, 36),
TextAlign = ContentAlignment.MiddleCenter
});
AddSmallLabel(cardGarantia, "Nº NF de venda", 10, 126);
cardGarantia.Controls.Add(new LV_TEXTBOX1
{
Location = P(10, 142),
Size = Sz(170, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
AddSmallLabel(cardGarantia, "Nº certificado de garantia", 198, 126);
cardGarantia.Controls.Add(new LV_TEXTBOX1
{
Location = P(198, 142),
Size = Sz(422, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
AddSmallLabel(cardGarantia, "Data da compra", 10, 184);
cardGarantia.Controls.Add(new DateTimePicker
{
Location = P(10, 200),
Width = S(170),
Format = DateTimePickerFormat.Short,
Font = new Font("Segoe UI", F(8.5f))
});
AddSmallLabel(cardGarantia, "Revendedor", 198, 184);
cardGarantia.Controls.Add(new LV_TEXTBOX1
{
Location = P(198, 200),
Size = Sz(422, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
tab.Controls.Add(cardGarantia);
// ── Card NF Entrada (x=660, y=10, w=480, h=120)
var cardNF = CreateInternalCard("Nota Fiscal Entrada / Remessa", R(660, 10, 490, 120));
AddSmallLabel(cardNF, "Número da NF", 10, 22);
cardNF.Controls.Add(new LV_TEXTBOX1
{
Location = P(10, 38),
Size = Sz(145, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
AddSmallLabel(cardNF, "Valor da NF", 168, 22);
cardNF.Controls.Add(new LV_TEXTBOX1
{
Location = P(168, 38),
Size = Sz(290, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
var cbFornecedorNF = AddComboBox(cardNF, "Emissor (Fornecedor)", 10, 72, 448);
cbFornecedorNF.Items.Add("Nenhum");
cbFornecedorNF.SelectedIndex = 0;
tab.Controls.Add(cardNF);
// ── Card Terceiros (x=660, y=138, w=480, h=132)
var cardTerceiros = CreateInternalCard("OS de Terceiros / Parceiros", R(660, 138, 490, 132));
AddSmallLabel(cardTerceiros, "Nº OS terceiros", 10, 22);
cardTerceiros.Controls.Add(new LV_TEXTBOX1
{
Location = P(10, 38),
Size = Sz(140, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
AddSmallLabel(cardTerceiros, "Nº OS Fabricante", 162, 22);
cardTerceiros.Controls.Add(new LV_TEXTBOX1
{
Location = P(162, 38),
Size = Sz(165, 26),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
});
var cbFornecedor = AddComboBox(cardTerceiros, "Emissor (Fornecedor)", 10, 72, 448);
cbFornecedor.Items.Add("Nenhum");
cbFornecedor.SelectedIndex = 0;
tab.Controls.Add(cardTerceiros);
tabDetalhes.TabPages.Add(tab);
}
#endregion
// ──────────────────────────────────────────────────────────────
// RODAPÉ (y=824, h=56)
// ──────────────────────────────────────────────────────────────
#region Rodapé
private void BuildRodape()
{
cardRodape = CreateCard(R(10, 824, 1160, 46), "");
cbTecnico = AddComboBox(cardRodape, "Técnico Responsável", 12, 5, 320);
cbPrioridade = AddComboBox(cardRodape, "Prioridade", 348, 5, 160);
cbPrioridade.Items.AddRange(new object[]
{
"Baixa", "Normal", "Alta", "Urgente", "Emergencial"
});
cbPrioridade.SelectedIndex = 1;
var btnFotos = new Button
{
Text = "Fotos / Docs",
Location = P(980, 8),
Size = Sz(155, 30),
FlatStyle = FlatStyle.Flat,
BackColor = AccentBlue,
ForeColor = Color.White,
Font = new Font("Segoe UI Semibold", F(8.5f)),
Cursor = Cursors.Hand
};
btnFotos.FlatAppearance.BorderSize = 0;
cardRodape.Controls.Add(btnFotos);
content.Controls.Add(cardRodape);
}
#endregion
// ──────────────────────────────────────────────────────────────
// HELPERS
// ──────────────────────────────────────────────────────────────
#region Helpers
private Panel CreateCard(Rectangle rect, string title)
{
var pnl = new Panel
{
Location = rect.Location,
Size = rect.Size,
BackColor = Color.White
};
pnl.Paint += CardPaint;
if (!string.IsNullOrWhiteSpace(title))
{
pnl.Controls.Add(new Label
{
Text = title,
Font = new Font("Segoe UI", F(9f), FontStyle.Bold),
ForeColor = AccentBlue,
Location = P(12, 10),
AutoSize = true
});
pnl.Controls.Add(new Panel
{
BackColor = BorderColor,
Location = P(12, 30),
Size = new Size(rect.Width - S(24), 1)
});
}
return pnl;
}
private LV_TEXTBOX1 AddModernInput(
Control parent,
string label,
int x, int y,
int width,
int height = 26)
{
parent.Controls.Add(new Label
{
Text = label,
Font = new Font("Segoe UI", F(8f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(x, y),
AutoSize = true
});
var txt = new LV_TEXTBOX1
{
Location = P(x, y + 16),
Size = Sz(width, height),
BorderColor = BorderColor,
BorderFocusColor = AccentBlue,
BackColor = Color.White
};
parent.Controls.Add(txt);
return txt;
}
private LV_TEXTBOX1 AddFinanceRow(Control parent, string text, int y)
{
parent.Controls.Add(new Label
{
Text = text,
Font = new Font("Segoe UI", F(8f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(10, y + 5),
AutoSize = true
});
var txt = new LV_TEXTBOX1
{
Location = P(118, y),
Size = Sz(164, 26),
TextAlign = HorizontalAlignment.Right,
BorderColor = BorderColor,
BorderFocusColor = AccentBlue
};
parent.Controls.Add(txt);
return txt;
}
private void AddSmallLabel(Control parent, string text, int x, int y)
{
parent.Controls.Add(new Label
{
Text = text,
Font = new Font("Segoe UI", F(8f), FontStyle.Bold),
ForeColor = TextDark,
Location = P(x, y),
AutoSize = true
});
}
private DateTimePicker CreatePicker(int x, int y, int width)
{
return new DateTimePicker
{
Location = P(x, y),
Width = S(width),
Format = DateTimePickerFormat.Custom,
CustomFormat = "dd/MM/yyyy HH:mm",
Font = new Font("Segoe UI", F(8.5f))
};
}
private ComboBox AddComboBox(Control parent, string label, int x, int y, int width)
{
AddSmallLabel(parent, label, x, y);
var cb = new ComboBox
{
Location = P(x, y + 16),
Size = Sz(width, 26),
Font = new Font("Segoe UI", F(8.5f)),
DropDownStyle = ComboBoxStyle.DropDownList
};
parent.Controls.Add(cb);
return cb;
}
// Grid padrão reutilizável
private DataGridView CriarGrid(Point location, Size size)
{
var grid = new DataGridView
{
Location = location,
Size = size,
BackgroundColor = Color.White,
BorderStyle = BorderStyle.FixedSingle,
AllowUserToAddRows = false,
AllowUserToDeleteRows = false,
AllowUserToResizeRows = false,
RowHeadersVisible = false,
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
MultiSelect = false,
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None,
EnableHeadersVisualStyles = false,
Font = new Font("Segoe UI", F(8f)),
GridColor = BorderColor,
ColumnHeadersHeight = S(26)
};
grid.ColumnHeadersDefaultCellStyle.BackColor = Color.FromArgb(245, 247, 250);
grid.ColumnHeadersDefaultCellStyle.ForeColor = TextDark;
grid.ColumnHeadersDefaultCellStyle.Font = new Font("Segoe UI", F(8f), FontStyle.Bold);
return grid;
}
// Botão lateral padronizado — overload simples
private Button BotaoLateral(string texto, int y, Color cor,
EventHandler? click = null)
{
var btn = new Button
{
Text = texto,
Location = P(8, y),
Size = Sz(148, 38),
FlatStyle = FlatStyle.Flat,
BackColor = cor,
ForeColor = Color.White,
Font = new Font("Segoe UI Semibold", F(8f)),
Cursor = Cursors.Hand
};
btn.FlatAppearance.BorderSize = 0;
if (click != null) btn.Click += click;
return btn;
}
// Botão lateral com posição e tamanho explícitos
private Button BotaoLateral(string texto, int y, Color cor,
Point location, Size size, EventHandler? click = null)
{
var btn = new Button
{
Text = texto,
Location = location,
Size = size,
FlatStyle = FlatStyle.Flat,
BackColor = cor,
ForeColor = Color.White,
Font = new Font("Segoe UI Semibold", F(8f)),
Cursor = Cursors.Hand
};
btn.FlatAppearance.BorderSize = 0;
if (click != null) btn.Click += click;
return btn;
}
#endregion
// ──────────────────────────────────────────────────────────────
// EVENTOS VISUAIS
// ──────────────────────────────────────────────────────────────
#region Eventos Visuais
private void CardPaint(object? sender, PaintEventArgs e)
{
var pnl = sender as Panel;
using var pen = new Pen(BorderColor);
e.Graphics.DrawRectangle(pen, 0, 0, pnl!.Width - 1, pnl.Height - 1);
}
private void DrawTab(object? sender, DrawItemEventArgs e)
{
var tab = tabDetalhes.TabPages[e.Index];
bool selected = e.Index == tabDetalhes.SelectedIndex;
using var back = new SolidBrush(selected ? AccentBlue : Color.FromArgb(230, 233, 238));
using var fore = new SolidBrush(selected ? Color.White : TextDark);
e.Graphics.FillRectangle(back, e.Bounds);
e.Graphics.DrawString(
tab.Text,
new Font("Segoe UI", F(8.5f), FontStyle.Bold),
fore,
e.Bounds,
new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
});
}
#endregion
// ──────────────────────────────────────────────────────────────
// MÉTODOS ABSTRATOS
// ──────────────────────────────────────────────────────────────
#region Métodos Abstratos
protected override void OnNovo() { }
protected override void OnAlterar() { }
protected override void OnExcluir() { }
protected override void OnLocalizar() { }
protected override void OnSalvar() { }
protected override void OnCancelar() { }
#endregion
}
}