Migrate ClideTheme.of(context) reads across the widget, feature, and shell layers to the unified ClideSettings.theme.of(context) facade (D-101), so theme/i18n/fonts/settings share one widget-facing entry. The facade delegates straight to ClideTheme, so behaviour is unchanged — goldens are unmoved. The low-level theme provider keeps its direct ClideTheme.of: the facade is built on it, and the two kernel sites (ClideTheme's own definition + the panels drag-resize widget) stay direct to avoid a widgets→kernel import cycle. Dead controller.dart/kernel.dart imports left by the sweep removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.0 KiB
Dart
69 lines
2.0 KiB
Dart
import 'package:clide/widgets/src/clide_settings.dart';
|
||
import 'package:flutter/widgets.dart';
|
||
|
||
/// Stateless painter producing a single-color icon. Every icon in
|
||
/// `widgets/src/icons/` subclasses this; widgets wrap with [ClideIcon]
|
||
/// for size + color-from-theme.
|
||
abstract class ClideIconPainter {
|
||
const ClideIconPainter();
|
||
|
||
/// Paint the icon into a unit square (0,0 .. 1,1).
|
||
void paint(Canvas canvas, Color color);
|
||
}
|
||
|
||
/// Draws nothing, but [ClideIcon] still reserves its `size×size` box — so a
|
||
/// caller can keep the icon slot for alignment without showing a glyph. This is
|
||
/// the *intentional* empty (e.g. a non-search filter field), distinct from an
|
||
/// unknown glyph name, which renders a visible `placeholder` error box (T-314).
|
||
class EmptyIconPainter extends ClideIconPainter {
|
||
const EmptyIconPainter();
|
||
|
||
@override
|
||
void paint(Canvas canvas, Color color) {}
|
||
|
||
@override
|
||
bool operator ==(Object other) => other is EmptyIconPainter;
|
||
|
||
@override
|
||
int get hashCode => (EmptyIconPainter).hashCode;
|
||
}
|
||
|
||
class ClideIcon extends StatelessWidget {
|
||
const ClideIcon(this.painter, {super.key, this.size = 14, this.color});
|
||
|
||
final ClideIconPainter painter;
|
||
final double size;
|
||
final Color? color;
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final resolved = color ?? ClideSettings.theme.of(context).surface.globalForeground;
|
||
return SizedBox(
|
||
width: size,
|
||
height: size,
|
||
child: CustomPaint(
|
||
size: Size(size, size),
|
||
painter: _IconPainterAdapter(painter: painter, color: resolved),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
|
||
class _IconPainterAdapter extends CustomPainter {
|
||
_IconPainterAdapter({required this.painter, required this.color});
|
||
|
||
final ClideIconPainter painter;
|
||
final Color color;
|
||
|
||
@override
|
||
void paint(Canvas canvas, Size size) {
|
||
canvas.save();
|
||
canvas.scale(size.width, size.height);
|
||
painter.paint(canvas, color);
|
||
canvas.restore();
|
||
}
|
||
|
||
@override
|
||
bool shouldRepaint(covariant _IconPainterAdapter old) => old.painter != painter || old.color != color;
|
||
}
|