/*******************************************************************************
* Copyright (c) 2007, 2010 Innoopract Informationssysteme GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Innoopract Informationssysteme GmbH - initial API and implementation
* EclipseSource - ongoing development
******************************************************************************/
package org.eclipse.swt.internal.graphics;
import java.math.BigDecimal;
import java.util.*;
import org.eclipse.rwt.SessionSingletonBase;
import org.eclipse.rwt.internal.service.ContextProvider;
import org.eclipse.rwt.internal.service.IServiceStateInfo;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Display;
final class TextSizeProbeStore {
// TODO [fappel]: improve probe text determination...
static String DEFAULT_PROBE;
static {
StringBuffer result = new StringBuffer();
for( int i = 33; i < 122; i++ ) {
if( i != 34 && i != 39 ) {
result.append( ( char ) i );
}
}
DEFAULT_PROBE = result.toString();
}
private static final String PROBE_REQUESTS
= TextSizeProbeStore.class.getName() + ".ProbeRequests";
private static Map probes = new HashMap();
private Map probeResults = new HashMap();
public interface IProbe {
FontData getFontData();
String getString();
String getJSProbeParam();
}
public interface IProbeResult {
IProbe getProbe();
Point getSize();
float getAvgCharWidth();
}
private static final class ProbeImpl implements IProbe {
private final String probeText;
private final FontData fontData;
private String jsProbeParam;
private ProbeImpl( final String probeText, final FontData fontData ) {
this.probeText = probeText;
this.fontData = fontData;
this.jsProbeParam = createProbeParam( this );
}
public FontData getFontData() {
return fontData;
}
public String getString() {
return probeText;
}
public String getJSProbeParam() {
if( "".equals( jsProbeParam ) ) {
jsProbeParam = createProbeParam( this );
}
return jsProbeParam;
}
}
private TextSizeProbeStore() {
// prevent instance creation
}
static TextSizeProbeStore getInstance() {
Object instance
= SessionSingletonBase.getInstance( TextSizeProbeStore.class );
return ( TextSizeProbeStore )instance;
}
IProbeResult getProbeResult( final FontData fontData ) {
return ( IProbeResult )probeResults.get( fontData );
}
boolean containsProbeResult( final FontData fontData ) {
return getProbeResult( fontData ) != null;
}
IProbeResult createProbeResult( final IProbe probe, final Point size ) {
FontData fontData = probe.getFontData();
IProbeResult result = new IProbeResult() {
private float avgCharWidth;
public IProbe getProbe() {
return probe;
}
public Point getSize() {
return size;
}
public float getAvgCharWidth() {
if( avgCharWidth == 0 ) {
BigDecimal width = new BigDecimal( getSize().x );
BigDecimal charCount
= new BigDecimal( getProbe().getString().length() );
int roundingMethod = BigDecimal.ROUND_HALF_UP;
avgCharWidth
= width.divide( charCount, 2, roundingMethod ).floatValue();
}
return avgCharWidth;
}
};
probeResults.put( fontData, result );
return result;
}
////////////////////////////
// application global probes
public static IProbe[] getProbeList() {
IProbe[] result;
synchronized( probes ) {
if( probes.isEmpty() ) {
FontData[] fontList = TextSizeStorageRegistry.obtain().getFontList();
for( int i = 0; i < fontList.length; i++ ) {
createProbe( fontList[ i ], getProbeString( fontList[ i ] ) );
}
}
result = new IProbe[ probes.size() ];
probes.values().toArray( result );
}
return result;
}
private static String getProbeString( final FontData fontData ) {
// TODO [fappel]: probe string determination different from default
return DEFAULT_PROBE;
}
static IProbe getProbe( final FontData font ) {
IProbe result;
synchronized( probes ) {
result = ( IProbe )probes.get( font );
}
return result;
}
static boolean containsProbe( final FontData fontData ) {
return getProbe( fontData ) != null;
}
static IProbe createProbe( final FontData fontData, final String probeText ) {
IProbe result = new ProbeImpl( probeText, fontData );
synchronized( probes ) {
probes.put( fontData, result );
}
TextSizeStorageRegistry.obtain().storeFont( fontData );
return result;
}
static void reset() {
synchronized( probes ) {
ITextSizeStorage registry = TextSizeStorageRegistry.obtain();
if( registry instanceof DefaultTextSizeStorage ) {
( ( DefaultTextSizeStorage )registry ).resetFontList();
}
probes.clear();
}
}
static void addProbeRequest( final FontData font ) {
IProbe probe = getProbe( font );
if( probe == null ) {
FontData fontData = font;
probe = createProbe( fontData, getProbeString( fontData ) );
}
getProbeRequestsInternal().add( probe );
}
static IProbe[] getProbeRequests() {
Set probeRequests = getProbeRequestsInternal();
IProbe[] result = new IProbe[ probeRequests.size() ];
probeRequests.toArray( result );
return result;
}
//////////////////
// helping methods
private static String createProbeParam( final IProbe probe ) {
StringBuffer result = new StringBuffer();
final Display display = Display.getCurrent();
if( display != null ) {
result.append( "[ " );
result.append( probe.getFontData().hashCode() );
result.append( ", " );
result.append( "\"" );
result.append( probe.getString() );
result.append( "\", " );
result.append(
TextSizeDeterminationFacade.createFontParam( probe.getFontData() ) );
result.append( " ]" );
}
return result.toString();
}
private static Set getProbeRequestsInternal() {
IServiceStateInfo stateInfo = ContextProvider.getStateInfo();
Set result = ( Set )stateInfo.getAttribute( PROBE_REQUESTS );
if( result == null ) {
result = new HashSet();
stateInfo.setAttribute( PROBE_REQUESTS, result );
}
return result;
}
}