@@ -19,7 +19,12 @@ import * as browserEvents from './browser_events.js';
1919import * as Css from './css.js' ;
2020import * as dom from './utils/dom.js' ;
2121import * as dropDownDiv from './dropdowndiv.js' ;
22- import { Field , FieldConfig , FieldValidator } from './field.js' ;
22+ import {
23+ Field ,
24+ FieldConfig ,
25+ FieldValidator ,
26+ UnattachedFieldError ,
27+ } from './field.js' ;
2328import * as fieldRegistry from './field_registry.js' ;
2429import * as aria from './utils/aria.js' ;
2530import * as colour from './utils/colour.js' ;
@@ -168,29 +173,118 @@ export class FieldColour extends Field<string> {
168173 this . getConstants ( ) ! . FIELD_COLOUR_DEFAULT_WIDTH ,
169174 this . getConstants ( ) ! . FIELD_COLOUR_DEFAULT_HEIGHT ,
170175 ) ;
171- if ( ! this . getConstants ( ) ! . FIELD_COLOUR_FULL_BLOCK ) {
172- this . createBorderRect_ ( ) ;
173- this . getBorderRect ( ) . style [ 'fillOpacity' ] = '1' ;
174- } else if ( this . sourceBlock_ instanceof BlockSvg ) {
175- this . clickTarget_ = this . sourceBlock_ . getSvgRoot ( ) ;
176+ this . createBorderRect_ ( ) ;
177+ this . getBorderRect ( ) . style [ 'fillOpacity' ] = '1' ;
178+ this . getBorderRect ( ) . setAttribute ( 'stroke' , '#fff' ) ;
179+ if ( this . isFullBlockField ( ) ) {
180+ this . clickTarget_ = ( this . sourceBlock_ as BlockSvg ) . getSvgRoot ( ) ;
176181 }
177182 }
178183
184+ protected override isFullBlockField ( ) : boolean {
185+ const block = this . getSourceBlock ( ) ;
186+ if ( ! block ) throw new UnattachedFieldError ( ) ;
187+
188+ const constants = this . getConstants ( ) ;
189+ return block . isSimpleReporter ( ) && ! ! constants ?. FIELD_COLOUR_FULL_BLOCK ;
190+ }
191+
179192 /**
180193 * Updates text field to match the colour/style of the block.
181194 */
182195 override applyColour ( ) {
183- if ( ! this . getConstants ( ) ! . FIELD_COLOUR_FULL_BLOCK ) {
184- if ( this . borderRect_ ) {
185- this . borderRect_ . style . fill = this . getValue ( ) as string ;
186- }
187- } else if ( this . sourceBlock_ instanceof BlockSvg ) {
188- this . sourceBlock_ . pathObject . svgPath . setAttribute (
189- 'fill' ,
190- this . getValue ( ) as string ,
191- ) ;
192- this . sourceBlock_ . pathObject . svgPath . setAttribute ( 'stroke' , '#fff' ) ;
196+ const block = this . getSourceBlock ( ) as BlockSvg | null ;
197+ if ( ! block ) throw new UnattachedFieldError ( ) ;
198+
199+ if ( ! this . fieldGroup_ ) return ;
200+
201+ const borderRect = this . borderRect_ ;
202+ if ( ! borderRect ) {
203+ throw new Error ( 'The border rect has not been initialized' ) ;
204+ }
205+
206+ if ( ! this . isFullBlockField ( ) ) {
207+ borderRect . style . display = 'block' ;
208+ borderRect . style . fill = this . getValue ( ) as string ;
209+ } else {
210+ borderRect . style . display = 'none' ;
211+ // In general, do *not* let fields control the color of blocks. Having the
212+ // field control the color is unexpected, and could have performance
213+ // impacts.
214+ block . pathObject . svgPath . setAttribute ( 'fill' , this . getValue ( ) as string ) ;
215+ block . pathObject . svgPath . setAttribute ( 'stroke' , '#fff' ) ;
216+ }
217+ }
218+
219+ /**
220+ * Returns the height and width of the field.
221+ *
222+ * This should *in general* be the only place render_ gets called from.
223+ *
224+ * @returns Height and width.
225+ */
226+ override getSize ( ) : Size {
227+ if ( this . getConstants ( ) ?. FIELD_COLOUR_FULL_BLOCK ) {
228+ // In general, do *not* let fields control the color of blocks. Having the
229+ // field control the color is unexpected, and could have performance
230+ // impacts.
231+ // Full block fields have more control of the block than they should
232+ // (i.e. updating fill colour). Whenever we get the size, the field may
233+ // no longer be a full-block field, so we need to rerender.
234+ this . render_ ( ) ;
235+ this . isDirty_ = false ;
193236 }
237+ return super . getSize ( ) ;
238+ }
239+
240+ /**
241+ * Updates the colour of the block to reflect whether this is a full
242+ * block field or not.
243+ */
244+ protected override render_ ( ) {
245+ super . render_ ( ) ;
246+
247+ const block = this . getSourceBlock ( ) as BlockSvg | null ;
248+ if ( ! block ) throw new UnattachedFieldError ( ) ;
249+ // In general, do *not* let fields control the color of blocks. Having the
250+ // field control the color is unexpected, and could have performance
251+ // impacts.
252+ // Whenever we render, the field may no longer be a full-block-field so
253+ // we need to update the colour.
254+ if ( this . getConstants ( ) ! . FIELD_COLOUR_FULL_BLOCK ) block . applyColour ( ) ;
255+ }
256+
257+ /**
258+ * Updates the size of the field based on whether it is a full block field
259+ * or not.
260+ *
261+ * @param margin margin to use when positioning the field.
262+ */
263+ protected updateSize_ ( margin ?: number ) {
264+ const constants = this . getConstants ( ) ;
265+ const xOffset =
266+ margin !== undefined
267+ ? margin
268+ : ! this . isFullBlockField ( )
269+ ? constants ! . FIELD_BORDER_RECT_X_PADDING
270+ : 0 ;
271+ let totalWidth = xOffset * 2 ;
272+ let contentWidth = 0 ;
273+ if ( ! this . isFullBlockField ( ) ) {
274+ contentWidth = constants ! . FIELD_COLOUR_DEFAULT_WIDTH ;
275+ totalWidth += contentWidth ;
276+ }
277+
278+ let totalHeight = constants ! . FIELD_TEXT_HEIGHT ;
279+ if ( ! this . isFullBlockField ( ) ) {
280+ totalHeight = Math . max ( totalHeight , constants ! . FIELD_BORDER_RECT_HEIGHT ) ;
281+ }
282+
283+ this . size_ . height = totalHeight ;
284+ this . size_ . width = totalWidth ;
285+
286+ this . positionTextElement_ ( xOffset , contentWidth ) ;
287+ this . positionBorderRect_ ( ) ;
194288 }
195289
196290 /**
@@ -206,26 +300,6 @@ export class FieldColour extends Field<string> {
206300 return colour . parse ( newValue ) ;
207301 }
208302
209- /**
210- * Update the value of this colour field, and update the displayed colour.
211- *
212- * @param newValue The value to be saved. The default validator guarantees
213- * that this is a colour in '#rrggbb' format.
214- */
215- protected override doValueUpdate_ ( newValue : string ) {
216- this . value_ = newValue ;
217- if ( this . borderRect_ ) {
218- this . borderRect_ . style . fill = newValue ;
219- } else if (
220- this . sourceBlock_ &&
221- this . sourceBlock_ . rendered &&
222- this . sourceBlock_ instanceof BlockSvg
223- ) {
224- this . sourceBlock_ . pathObject . svgPath . setAttribute ( 'fill' , newValue ) ;
225- this . sourceBlock_ . pathObject . svgPath . setAttribute ( 'stroke' , '#fff' ) ;
226- }
227- }
228-
229303 /**
230304 * Get the text for this field. Used when the block is collapsed.
231305 *
0 commit comments