Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
8c2c5022
Commit
8c2c5022
authored
Aug 24, 2017
by
Hans Muller
Committed by
GitHub
Aug 24, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated I18N API for Flutter (#11497)
parent
7676e511
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1061 additions
and
237 deletions
+1061
-237
regenerate.md
examples/stocks/lib/i18n/regenerate.md
+30
-7
stock_messages_all.dart
examples/stocks/lib/i18n/stock_messages_all.dart
+2
-1
main.dart
examples/stocks/lib/main.dart
+11
-10
stock_strings.dart
examples/stocks/lib/stock_strings.dart
+31
-18
locale_test.dart
examples/stocks/test/locale_test.dart
+10
-0
material.dart
packages/flutter/lib/material.dart
+1
-0
app.dart
packages/flutter/lib/src/material/app.dart
+39
-11
app_bar.dart
packages/flutter/lib/src/material/app_bar.dart
+2
-1
back_button.dart
packages/flutter/lib/src/material/back_button.dart
+3
-2
date_picker.dart
packages/flutter/lib/src/material/date_picker.dart
+3
-2
material_localizations.dart
...ages/flutter/lib/src/material/material_localizations.dart
+58
-0
app.dart
packages/flutter/lib/src/widgets/app.dart
+23
-28
binding.dart
packages/flutter/lib/src/widgets/binding.dart
+33
-17
locale_query.dart
packages/flutter/lib/src/widgets/locale_query.dart
+0
-45
localizations.dart
packages/flutter/lib/src/widgets/localizations.dart
+346
-0
widgets.dart
packages/flutter/lib/widgets.dart
+1
-1
date_picker_test.dart
packages/flutter/test/material/date_picker_test.dart
+56
-62
locale_query_test.dart
packages/flutter/test/widgets/locale_query_test.dart
+0
-32
localizations_test.dart
packages/flutter/test/widgets/localizations_test.dart
+412
-0
No files found.
examples/stocks/lib/i18n/regenerate.md
View file @
8c2c5022
To rebuild the i18n files:
## Regenerating the i18n files
The files in this directory are based on ../lib/stock_strings.dart
which defines all of the localizable strings used by the stocks
app. The stocks app uses
the
[
Dart `intl` package
](
https://github.com/dart-lang/intl
)
.
Rebuilding everything requires two steps.
With the
`examples/stocks`
as the current directory, generate
`intl_messages.arb`
from
`lib/stock_strings.dart`
:
```
pub run intl_translation:generate_from_arb \
--output-dir=lib/i18n \
--generated-file-prefix=stock_ \
--no-use-deferred-loading \
lib/*.dart \
lib/i18n/*.arb
flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/i18n lib/stock_strings.dart
```
The
`intl_messages.arb`
file is a JSON format map with one entry for
each
`Intl.message()`
function defined in
`stock_strings.dart`
. This
file was used to create the English and Spanish localizations,
`stocks_en.arb`
and
`stocks_es.arb`
. The
`intl_messages.arb`
wasn't
checked into the repository, since it only serves as a template for
the other
`.arb`
files.
With the
`examples/stocks`
as the current directory, generate a
`stock_messages_<locale>.dart`
for each
`stocks_<locale>.arb`
file and
`stock_messages_all.dart`
, which imports all of the messages files:
```
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/i18n \
--generated-file-prefix=stock_ --no-use-deferred-loading lib/*.dart lib/i18n/stocks_*.arb
```
The
`StockStrings`
class uses the generated
`initializeMessages()`
function (
`stock_messages_all.dart`
) to load the localized messages
and
`Intl.message()`
to look them up.
examples/stocks/lib/i18n/stock_messages_all.dart
View file @
8c2c5022
...
...
@@ -11,7 +11,8 @@ import 'package:intl/src/intl_helpers.dart';
import
'stock_messages_en.dart'
as
messages_en
;
import
'stock_messages_es.dart'
as
messages_es
;
Map
<
String
,
Function
>
_deferredLibraries
=
{
typedef
Future
<
dynamic
>
LibraryLoader
();
Map
<
String
,
LibraryLoader
>
_deferredLibraries
=
{
'en'
:
()
=>
new
Future
.
value
(
null
),
'es'
:
()
=>
new
Future
.
value
(
null
),
};
...
...
examples/stocks/lib/main.dart
View file @
8c2c5022
...
...
@@ -13,9 +13,7 @@ import 'package:flutter/rendering.dart' show
debugPaintLayerBordersEnabled
,
debugPaintPointersEnabled
,
debugRepaintRainbowEnabled
;
import
'package:intl/intl.dart'
;
import
'i18n/stock_messages_all.dart'
;
import
'stock_data.dart'
;
import
'stock_home.dart'
;
import
'stock_settings.dart'
;
...
...
@@ -23,6 +21,14 @@ import 'stock_strings.dart';
import
'stock_symbol_viewer.dart'
;
import
'stock_types.dart'
;
class
_StocksLocalizationsDelegate
extends
LocalizationsDelegate
<
StockStrings
>
{
@override
Future
<
StockStrings
>
load
(
Locale
locale
)
=>
StockStrings
.
load
(
locale
);
@override
bool
shouldReload
(
_StocksLocalizationsDelegate
old
)
=>
false
;
}
class
StocksApp
extends
StatefulWidget
{
@override
StocksAppState
createState
()
=>
new
StocksAppState
();
...
...
@@ -99,13 +105,6 @@ class StocksAppState extends State<StocksApp> {
return
null
;
}
Future
<
LocaleQueryData
>
_onLocaleChanged
(
Locale
locale
)
async
{
final
String
localeString
=
locale
.
toString
();
await
initializeMessages
(
localeString
);
Intl
.
defaultLocale
=
localeString
;
return
StockStrings
.
instance
;
}
@override
Widget
build
(
BuildContext
context
)
{
assert
(()
{
...
...
@@ -119,6 +118,9 @@ class StocksAppState extends State<StocksApp> {
return
new
MaterialApp
(
title:
'Stocks'
,
theme:
theme
,
localizationsDelegates:
<
_StocksLocalizationsDelegate
>[
new
_StocksLocalizationsDelegate
(),
],
debugShowMaterialGrid:
_configuration
.
debugShowGrid
,
showPerformanceOverlay:
_configuration
.
showPerformanceOverlay
,
showSemanticsDebugger:
_configuration
.
showSemanticsDebugger
,
...
...
@@ -127,7 +129,6 @@ class StocksAppState extends State<StocksApp> {
'/settings'
:
(
BuildContext
context
)
=>
new
StockSettings
(
_configuration
,
configurationUpdater
)
},
onGenerateRoute:
_getRoute
,
onLocaleChanged:
_onLocaleChanged
);
}
}
...
...
examples/stocks/lib/stock_strings.dart
View file @
8c2c5022
...
...
@@ -2,39 +2,52 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:intl/intl.dart'
;
import
'package:flutter/widgets.dart'
;
// Wrappers for strings that are shown in the UI. The strings can be
// translated for different locales using the Dart intl package.
//
// Locale-specific values for the strings live in the i18n/*.arb files.
//
// To generate the stock_messages_*.dart files from the ARB files, run:
// pub run intl:generate_from_arb --output-dir=lib/i18n --generated-file-prefix=stock_ --no-use-deferred-loading lib/stock_strings.dart lib/i18n/stocks_*.arb
import
'i18n/stock_messages_all.dart'
;
class
StockStrings
extends
LocaleQueryData
{
static
StockStrings
of
(
BuildContext
context
)
{
return
LocaleQuery
.
of
(
context
);
// Information about how this file relates to i18n/stock_messages_all.dart and how the i18n files
// were generated can be found in i18n/regenerate.md.
class
StockStrings
{
StockStrings
(
Locale
locale
)
:
_localeName
=
locale
.
toString
();
final
String
_localeName
;
static
Future
<
StockStrings
>
load
(
Locale
locale
)
{
return
initializeMessages
(
locale
.
toString
())
.
then
((
Null
_
)
{
return
new
StockStrings
(
locale
);
});
}
static
final
StockStrings
instance
=
new
StockStrings
();
static
StockStrings
of
(
BuildContext
context
)
{
return
Localizations
.
of
<
StockStrings
>(
context
,
StockStrings
);
}
String
title
()
=>
Intl
.
message
(
'Stocks'
,
name:
'title'
,
desc:
'Title for the Stocks application'
);
String
title
()
{
return
Intl
.
message
(
'<Stocks>'
,
name:
'title'
,
desc:
'Title for the Stocks application'
,
locale:
_localeName
,
);
}
String
market
()
=>
Intl
.
message
(
'MARKET'
,
name:
'market'
,
desc:
'Label for the Market tab'
desc:
'Label for the Market tab'
,
locale:
_localeName
,
);
String
portfolio
()
=>
Intl
.
message
(
'PORTFOLIO'
,
name:
'portfolio'
,
desc:
'Label for the Portfolio tab'
desc:
'Label for the Portfolio tab'
,
locale:
_localeName
,
);
}
examples/stocks/test/locale_test.dart
View file @
8c2c5022
...
...
@@ -13,9 +13,19 @@ void main() {
stocks
.
main
();
await
tester
.
idle
();
// see https://github.com/flutter/flutter/issues/1865
await
tester
.
pump
();
// The initial test app's locale is "_", so we're seeing the fallback translation here.
expect
(
find
.
text
(
'MARKET'
),
findsOneWidget
);
await
tester
.
binding
.
setLocale
(
'es'
,
'US'
);
await
tester
.
idle
();
// The Localizations widget has been built with the new locale. The
// new locale's strings are loaded asynchronously, so we're still
// displaying the previous locale's strings.
await
tester
.
pump
();
expect
(
find
.
text
(
'MARKET'
),
findsOneWidget
);
// The localized strings have finished loading and dependent
// widgets have been updated.
await
tester
.
pump
();
expect
(
find
.
text
(
'MERCADO'
),
findsOneWidget
);
});
...
...
packages/flutter/lib/material.dart
View file @
8c2c5022
...
...
@@ -57,6 +57,7 @@ export 'src/material/ink_well.dart';
export
'src/material/input_decorator.dart'
;
export
'src/material/list_tile.dart'
;
export
'src/material/material.dart'
;
export
'src/material/material_localizations.dart'
;
export
'src/material/mergeable_material.dart'
;
export
'src/material/page.dart'
;
export
'src/material/paginated_data_table.dart'
;
...
...
packages/flutter/lib/src/material/app.dart
View file @
8c2c5022
...
...
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
...
...
@@ -10,11 +12,10 @@ import 'arc.dart';
import
'colors.dart'
;
import
'floating_action_button.dart'
;
import
'icons.dart'
;
import
'material_localizations.dart'
;
import
'page.dart'
;
import
'theme.dart'
;
export
'dart:ui'
show
Locale
;
const
TextStyle
_errorTextStyle
=
const
TextStyle
(
color:
const
Color
(
0xD0FF0000
),
fontFamily:
'monospace'
,
...
...
@@ -25,6 +26,16 @@ const TextStyle _errorTextStyle = const TextStyle(
decorationStyle:
TextDecorationStyle
.
double
);
class
_MaterialLocalizationsDelegate
extends
LocalizationsDelegate
<
MaterialLocalizations
>
{
const
_MaterialLocalizationsDelegate
();
@override
Future
<
MaterialLocalizations
>
load
(
Locale
locale
)
=>
MaterialLocalizations
.
load
(
locale
);
@override
bool
shouldReload
(
_MaterialLocalizationsDelegate
old
)
=>
false
;
}
/// An application that uses material design.
///
/// A convenience widget that wraps a number of widgets that are commonly
...
...
@@ -80,7 +91,8 @@ class MaterialApp extends StatefulWidget {
this
.
initialRoute
,
this
.
onGenerateRoute
,
this
.
onUnknownRoute
,
this
.
onLocaleChanged
,
this
.
locale
,
this
.
localizationsDelegates
,
this
.
navigatorObservers
:
const
<
NavigatorObserver
>[],
this
.
debugShowMaterialGrid
:
false
,
this
.
showPerformanceOverlay
:
false
,
...
...
@@ -129,10 +141,9 @@ class MaterialApp extends StatefulWidget {
/// normally, unless [initialRoute] is specified. It's also the route that's
/// displayed if the [initialRoute] can't be displayed.
///
/// To be able to directly call [Theme.of], [MediaQuery.of],
/// [LocaleQuery.of], etc, in the code sets the [home] argument in
/// the constructor, you can use a [Builder] widget to get a
/// [BuildContext].
/// To be able to directly call [Theme.of], [MediaQuery.of], etc, in the code
/// that sets the [home] argument in the constructor, you can use a [Builder]
/// widget to get a [BuildContext].
///
/// If [home] is specified, then [routes] must not include an entry for `/`,
/// as [home] takes its place.
...
...
@@ -210,9 +221,16 @@ class MaterialApp extends StatefulWidget {
/// message.
final
RouteFactory
onUnknownRoute
;
/// Callback that is called when the operating system changes the
/// current locale.
final
LocaleChangedCallback
onLocaleChanged
;
/// The initial locale for this app's [Localizations] widget.
///
/// If the `locale` is null the system's locale value is used.
final
Locale
locale
;
/// The delegates for this app's [Localizations] widget.
///
/// The delegates collectively define all of the localized resources
/// for this application's [Localizations] widget.
final
Iterable
<
LocalizationsDelegate
<
dynamic
>>
localizationsDelegates
;
/// Turns on a performance overlay.
///
...
...
@@ -297,6 +315,14 @@ class _MaterialAppState extends State<MaterialApp> {
_heroController
=
new
HeroController
(
createRectTween:
_createRectTween
);
}
// Combine the Localizations for Material with the ones contributed
// by the localizationsDelegates parameter, if any.
Iterable
<
LocalizationsDelegate
<
dynamic
>>
_createLocalizationsDelegates
()
sync
*
{
yield
const
_MaterialLocalizationsDelegate
();
if
(
widget
.
localizationsDelegates
!=
null
)
yield
*
widget
.
localizationsDelegates
;
}
RectTween
_createRectTween
(
Rect
begin
,
Rect
end
)
{
return
new
MaterialRectArcTween
(
begin:
begin
,
end:
end
);
}
...
...
@@ -319,6 +345,7 @@ class _MaterialAppState extends State<MaterialApp> {
return
null
;
}
Route
<
dynamic
>
_onUnknownRoute
(
RouteSettings
settings
)
{
assert
(()
{
if
(
widget
.
onUnknownRoute
==
null
)
{
...
...
@@ -369,7 +396,8 @@ class _MaterialAppState extends State<MaterialApp> {
initialRoute:
widget
.
initialRoute
,
onGenerateRoute:
_onGenerateRoute
,
onUnknownRoute:
_onUnknownRoute
,
onLocaleChanged:
widget
.
onLocaleChanged
,
locale:
widget
.
locale
,
localizationsDelegates:
_createLocalizationsDelegates
(),
showPerformanceOverlay:
widget
.
showPerformanceOverlay
,
checkerboardRasterCacheImages:
widget
.
checkerboardRasterCacheImages
,
checkerboardOffscreenLayers:
widget
.
checkerboardOffscreenLayers
,
...
...
packages/flutter/lib/src/material/app_bar.dart
View file @
8c2c5022
...
...
@@ -15,6 +15,7 @@ import 'flexible_space_bar.dart';
import
'icon_button.dart'
;
import
'icons.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'page.dart'
;
import
'scaffold.dart'
;
import
'tabs.dart'
;
...
...
@@ -352,7 +353,7 @@ class _AppBarState extends State<AppBar> {
leading
=
new
IconButton
(
icon:
const
Icon
(
Icons
.
menu
),
onPressed:
_handleDrawerButton
,
tooltip:
'Open navigation menu'
// TODO(ianh): Figure out how to localize this string
tooltip:
MaterialLocalizations
.
of
(
context
).
openAppDrawerTooltip
,
);
}
else
{
if
(
canPop
)
...
...
packages/flutter/lib/src/material/back_button.dart
View file @
8c2c5022
...
...
@@ -6,6 +6,7 @@ import 'package:flutter/widgets.dart';
import
'icon_button.dart'
;
import
'icons.dart'
;
import
'material_localizations.dart'
;
import
'theme.dart'
;
/// A "back" icon that's appropriate for the current [TargetPlatform].
...
...
@@ -83,7 +84,7 @@ class BackButton extends StatelessWidget {
return
new
IconButton
(
icon:
const
BackButtonIcon
(),
color:
color
,
tooltip:
'Back'
,
// TODO(ianh): Figure out how to localize this string
tooltip:
MaterialLocalizations
.
of
(
context
).
backButtonTooltip
,
onPressed:
()
{
Navigator
.
of
(
context
).
maybePop
();
}
...
...
@@ -115,7 +116,7 @@ class CloseButton extends StatelessWidget {
Widget
build
(
BuildContext
context
)
{
return
new
IconButton
(
icon:
const
Icon
(
Icons
.
close
),
tooltip:
'Close'
,
// TODO(ianh): Figure out how to localize this string
tooltip:
MaterialLocalizations
.
of
(
context
).
closeButtonTooltip
,
onPressed:
()
{
Navigator
.
of
(
context
).
maybePop
();
},
...
...
packages/flutter/lib/src/material/date_picker.dart
View file @
8c2c5022
...
...
@@ -23,6 +23,7 @@ import 'icon_button.dart';
import
'icons.dart'
;
import
'ink_well.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'theme.dart'
;
import
'typography.dart'
;
...
...
@@ -548,7 +549,7 @@ class _MonthPickerState extends State<MonthPicker> {
left:
8.0
,
child:
new
IconButton
(
icon:
const
Icon
(
Icons
.
chevron_left
),
tooltip:
'Previous month'
,
tooltip:
MaterialLocalizations
.
of
(
context
).
previousMonthTooltip
,
onPressed:
_isDisplayingFirstMonth
?
null
:
_handlePreviousMonth
,
),
),
...
...
@@ -557,7 +558,7 @@ class _MonthPickerState extends State<MonthPicker> {
right:
8.0
,
child:
new
IconButton
(
icon:
const
Icon
(
Icons
.
chevron_right
),
tooltip:
'Next month'
,
tooltip:
MaterialLocalizations
.
of
(
context
).
nextMonthTooltip
,
onPressed:
_isDisplayingLastMonth
?
null
:
_handleNextMonth
,
),
),
...
...
packages/flutter/lib/src/material/material_localizations.dart
0 → 100644
View file @
8c2c5022
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
/// Default localized resource values for the material widgets.
///
/// This class is just a placeholder, it only provides English values.
class
MaterialLocalizations
{
const
MaterialLocalizations
.
_
(
this
.
locale
)
:
assert
(
locale
!=
null
);
/// The locale for which the values of this class's localized resources
/// have been translated.
final
Locale
locale
;
/// Creates an object that provides default localized resource values for the
/// for the widgets of the material library.
///
/// This method is typically used to create a [DefaultLocalizationsDelegate].
/// The [MaterialApp] does so by default.
static
Future
<
MaterialLocalizations
>
load
(
Locale
locale
)
{
return
new
SynchronousFuture
<
MaterialLocalizations
>(
new
MaterialLocalizations
.
_
(
locale
));
}
/// The `MaterialLocalizations` from the closest [Localizations] instance
/// that encloses the given context.
///
/// This method is just a convenient shorthand for:
/// `Localizations.of<MaterialLocalizations>(context, MaterialLocalizations)`.
///
/// References to the localized resources defined by this class are typically
/// written in terms of this method. For example:
/// ```dart
/// tooltip: MaterialLocalizations.of(context).backButtonTooltip,
/// ```
static
MaterialLocalizations
of
(
BuildContext
context
)
{
return
Localizations
.
of
<
MaterialLocalizations
>(
context
,
MaterialLocalizations
);
}
/// The tooltip for the leading [AppBar] menu (aka 'hamburger') button
String
get
openAppDrawerTooltip
=>
'Open navigation menu'
;
/// The [BackButton]'s tooltip.
String
get
backButtonTooltip
=>
'Back'
;
/// The [CloseButton]'s tooltip.
String
get
closeButtonTooltip
=>
'Close'
;
/// The tooltip for the [MonthPicker]'s "next month" button.
String
get
nextMonthTooltip
=>
'Next month'
;
/// The tooltip for the [MonthPicker]'s "previous month" button.
String
get
previousMonthTooltip
=>
'Previous month'
;
}
packages/flutter/lib/src/widgets/app.dart
View file @
8c2c5022
...
...
@@ -11,9 +11,8 @@ import 'package:flutter/rendering.dart';
import
'banner.dart'
;
import
'basic.dart'
;
import
'binding.dart'
;
import
'container.dart'
;
import
'framework.dart'
;
import
'local
e_query
.dart'
;
import
'local
izations
.dart'
;
import
'media_query.dart'
;
import
'navigator.dart'
;
import
'performance_overlay.dart'
;
...
...
@@ -22,10 +21,7 @@ import 'text.dart';
import
'title.dart'
;
import
'widget_inspector.dart'
;
/// Signature for a function that is called when the operating system changes the current locale.
///
/// Used by [WidgetsApp.onLocaleChanged].
typedef
Future
<
LocaleQueryData
>
LocaleChangedCallback
(
Locale
locale
);
export
'dart:ui'
show
Locale
;
/// A convenience class that wraps a number of widgets that are commonly
/// required for an application.
...
...
@@ -34,7 +30,7 @@ typedef Future<LocaleQueryData> LocaleChangedCallback(Locale locale);
/// back button to popping the [Navigator] or quitting the application.
///
/// See also: [CheckedModeBanner], [DefaultTextStyle], [MediaQuery],
/// [Local
eQuery
], [Title], [Navigator], [Overlay], [SemanticsDebugger] (the
/// [Local
izations
], [Title], [Navigator], [Overlay], [SemanticsDebugger] (the
/// widgets wrapped by this one).
///
/// The [onGenerateRoute] argument is required, and corresponds to
...
...
@@ -54,7 +50,8 @@ class WidgetsApp extends StatefulWidget {
@required
this
.
color
,
this
.
navigatorObservers
:
const
<
NavigatorObserver
>[],
this
.
initialRoute
,
this
.
onLocaleChanged
,
this
.
locale
,
this
.
localizationsDelegates
,
this
.
showPerformanceOverlay
:
false
,
this
.
checkerboardRasterCacheImages
:
false
,
this
.
checkerboardOffscreenLayers
:
false
,
...
...
@@ -130,9 +127,16 @@ class WidgetsApp extends StatefulWidget {
/// * [Navigator.pop], for removing a route from the stack.
final
String
initialRoute
;
/// Callback that is called when the operating system changes the
/// current locale.
final
LocaleChangedCallback
onLocaleChanged
;
/// The initial locale for this app's [Localizations] widget.
///
/// If the 'locale' is null the system's locale value is used.
final
Locale
locale
;
/// The delegates for this app's [Localizations] widget.
///
/// The delegates collectively define all of the localized resources
/// for this application's [Localizations] widget.
final
Iterable
<
LocalizationsDelegate
<
dynamic
>>
localizationsDelegates
;
/// Turns on a performance overlay.
/// https://flutter.io/debugging/#performanceoverlay
...
...
@@ -214,13 +218,13 @@ class WidgetsApp extends StatefulWidget {
class
_WidgetsAppState
extends
State
<
WidgetsApp
>
implements
WidgetsBindingObserver
{
GlobalObjectKey
<
NavigatorState
>
_navigator
;
Locale
QueryData
_localeData
;
Locale
_locale
;
@override
void
initState
()
{
super
.
initState
();
_navigator
=
new
GlobalObjectKey
<
NavigatorState
>(
this
);
didChangeLocale
(
ui
.
window
.
locale
)
;
_locale
=
ui
.
window
.
locale
;
WidgetsBinding
.
instance
.
addObserver
(
this
);
}
...
...
@@ -258,10 +262,9 @@ class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserv
@override
void
didChangeLocale
(
Locale
locale
)
{
if
(
widget
.
onLocaleChanged
!=
null
)
{
widget
.
onLocaleChanged
(
locale
).
then
<
Null
>((
LocaleQueryData
data
)
{
if
(
mounted
)
setState
(()
{
_localeData
=
data
;
});
if
(
locale
!=
_locale
)
{
setState
(()
{
_locale
=
locale
;
});
}
}
...
...
@@ -274,19 +277,11 @@ class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserv
@override
Widget
build
(
BuildContext
context
)
{
if
(
widget
.
onLocaleChanged
!=
null
&&
_localeData
==
null
)
{
// If the app expects a locale but we don't yet know the locale, then
// don't build the widgets now.
// TODO(ianh): Make this unnecessary. See https://github.com/flutter/flutter/issues/1865
// TODO(ianh): The following line should not be included in release mode, only in profile and debug modes.
WidgetsBinding
.
instance
.
preventThisFrameFromBeingReportedAsFirstFrame
();
return
new
Container
();
}
Widget
result
=
new
MediaQuery
(
data:
new
MediaQueryData
.
fromWindow
(
ui
.
window
),
child:
new
LocaleQuery
(
data:
_localeData
,
child:
new
Localizations
(
locale:
widget
.
locale
??
_locale
,
delegates:
widget
.
localizationsDelegates
,
child:
new
Title
(
title:
widget
.
title
,
color:
widget
.
color
,
...
...
packages/flutter/lib/src/widgets/binding.dart
View file @
8c2c5022
...
...
@@ -389,19 +389,35 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
}
bool
_needToReportFirstFrame
=
true
;
bool
_thisFrameWasUseful
=
true
;
int
_deferFirstFrameReportCount
=
0
;
bool
get
_reportFirstFrame
=>
_deferFirstFrameReportCount
==
0
;
/// Tell the framework
that the frame we are currently building
///
should not be considered to be a useful first frame
.
/// Tell the framework
not to report the frame it is building as a "useful"
///
first frame until there is a corresponding call to [allowFirstFrameReport]
.
///
/// This is used by [WidgetsApp] to report the first frame.
//
// TODO(ianh): This method should only be available in debug and profile modes.
void
preventThisFrameFromBeingReportedAsFirstFrame
()
{
_thisFrameWasUseful
=
false
;
void
deferFirstFrameReport
()
{
assert
(
_deferFirstFrameReportCount
>=
0
);
_deferFirstFrameReportCount
+=
1
;
}
void
_handleBuildScheduled
()
{
/// When called after [deferFirstFrameReport]: tell the framework to report
/// the frame it is building as a "useful" first frame.
///
/// This method may only be called once for each corresponding call
/// to [deferFirstFrameReport].
///
/// This is used by [WidgetsApp] to report the first frame.
//
// TODO(ianh): This method should only be available in debug and profile modes.
void
allowFirstFrameReport
()
{
assert
(
_deferFirstFrameReportCount
>=
1
);
_deferFirstFrameReportCount
-=
1
;
}
void
_handleBuildScheduled
()
{
// If we're in the process of building dirty elements, then changes
// should not trigger a new frame.
assert
(()
{
...
...
@@ -522,14 +538,10 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
}
// TODO(ianh): Following code should not be included in release mode, only profile and debug modes.
// See https://github.com/dart-lang/sdk/issues/27192
if
(
_needToReportFirstFrame
)
{
if
(
_thisFrameWasUseful
)
{
developer
.
Timeline
.
instantSync
(
'Widgets completed first useful frame'
);
developer
.
postEvent
(
'Flutter.FirstFrame'
,
<
String
,
dynamic
>{});
_needToReportFirstFrame
=
false
;
}
else
{
_thisFrameWasUseful
=
true
;
}
if
(
_needToReportFirstFrame
&&
_reportFirstFrame
)
{
developer
.
Timeline
.
instantSync
(
'Widgets completed first useful frame'
);
developer
.
postEvent
(
'Flutter.FirstFrame'
,
<
String
,
dynamic
>{});
_needToReportFirstFrame
=
false
;
}
}
...
...
@@ -556,11 +568,15 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
@override
Future
<
Null
>
performReassemble
()
{
_needToReportFirstFrame
=
true
;
preventThisFrameFromBeingReportedAsFirstFrame
();
deferFirstFrameReport
();
if
(
renderViewElement
!=
null
)
buildOwner
.
reassemble
(
renderViewElement
);
return
super
.
performReassemble
();
// TODO(hansmuller): eliminate the value variable after analyzer bug
// https://github.com/flutter/flutter/issues/11646 is fixed.
final
Future
<
Null
>
value
=
super
.
performReassemble
();
return
value
.
then
((
Null
_
)
{
allowFirstFrameReport
();
});
}
}
...
...
packages/flutter/lib/src/widgets/locale_query.dart
deleted
100644 → 0
View file @
7676e511
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/foundation.dart'
;
import
'framework.dart'
;
/// Superclass for locale-specific data provided by the application.
class
LocaleQueryData
{
}
// TODO(ianh): We need a better type here. This doesn't really make sense.
/// Establishes a subtree in which locale queries resolve to the given data.
class
LocaleQuery
extends
InheritedWidget
{
/// Creates a widget that provides [LocaleQueryData] to its descendants.
const
LocaleQuery
({
Key
key
,
@required
this
.
data
,
@required
Widget
child
})
:
assert
(
child
!=
null
),
super
(
key:
key
,
child:
child
);
/// The locale data for this subtree.
final
LocaleQueryData
data
;
/// The data from the closest instance of this class that encloses the given context.
///
/// Typical usage is as follows:
///
/// ```dart
/// MyLocaleData data = LocaleQueryData.of(context);
/// ```
static
LocaleQueryData
of
(
BuildContext
context
)
{
final
LocaleQuery
query
=
context
.
inheritFromWidgetOfExactType
(
LocaleQuery
);
return
query
?.
data
;
}
@override
bool
updateShouldNotify
(
LocaleQuery
old
)
=>
data
!=
old
.
data
;
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
description
)
{
super
.
debugFillProperties
(
description
);
description
.
add
(
new
DiagnosticsProperty
<
LocaleQueryData
>(
'data'
,
data
,
showName:
false
));
}
}
packages/flutter/lib/src/widgets/localizations.dart
0 → 100644
View file @
8c2c5022
This diff is collapsed.
Click to expand it.
packages/flutter/lib/widgets.dart
View file @
8c2c5022
...
...
@@ -45,7 +45,7 @@ export 'src/widgets/image.dart';
export
'src/widgets/image_icon.dart'
;
export
'src/widgets/implicit_animations.dart'
;
export
'src/widgets/layout_builder.dart'
;
export
'src/widgets/local
e_query
.dart'
;
export
'src/widgets/local
izations
.dart'
;
export
'src/widgets/media_query.dart'
;
export
'src/widgets/modal_barrier.dart'
;
export
'src/widgets/navigation_toolbar.dart'
;
...
...
packages/flutter/test/material/date_picker_test.dart
View file @
8c2c5022
...
...
@@ -28,94 +28,88 @@ void main() {
DateTime
_selectedDate
=
new
DateTime
(
2016
,
DateTime
.
JULY
,
26
);
await
tester
.
pumpWidget
(
new
Overlay
(
initialEntries:
<
OverlayEntry
>[
new
OverlayEntry
(
builder:
(
BuildContext
context
)
=>
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
new
Positioned
(
width:
400.0
,
child:
new
SingleChildScrollView
(
child:
new
Material
(
child:
new
MonthPicker
(
firstDate:
new
DateTime
(
0
),
lastDate:
new
DateTime
(
9999
),
key:
_datePickerKey
,
selectedDate:
_selectedDate
,
onChanged:
(
DateTime
value
)
{
setState
(()
{
_selectedDate
=
value
;
});
},
),
),
new
MaterialApp
(
home:
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
new
Container
(
width:
400.0
,
child:
new
SingleChildScrollView
(
child:
new
Material
(
child:
new
MonthPicker
(
firstDate:
new
DateTime
(
0
),
lastDate:
new
DateTime
(
9999
),
key:
_datePickerKey
,
selectedDate:
_selectedDate
,
onChanged:
(
DateTime
value
)
{
setState
(()
{
_selectedDate
=
value
;
});
},
),
)
;
}
,
)
,
)
,
]
,
)
,
)
,
)
,
)
;
}
,
)
,
)
);
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
JULY
,
26
)));
await
tester
.
tapAt
(
const
Offset
(
50.0
,
100.0
));
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
JULY
,
26
))
);
await
tester
.
pumpAndSettle
(
);
await
tester
.
pump
(
const
Duration
(
seconds:
2
));
await
tester
.
tapAt
(
const
Offset
(
300.0
,
100.0
));
await
tester
.
tap
(
find
.
text
(
'1'
));
await
tester
.
pumpAndSettle
();
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
JULY
,
1
)));
await
tester
.
pump
(
const
Duration
(
seconds:
2
));
await
tester
.
tap
At
(
const
Offset
(
380.0
,
20.0
));
await
tester
.
pumpAndSettle
(
const
Duration
(
milliseconds:
100
)
);
await
tester
.
tap
(
find
.
byTooltip
(
'Next month'
));
await
tester
.
pumpAndSettle
();
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
JULY
,
1
)));
await
tester
.
tapAt
(
const
Offset
(
300.0
,
100.0
));
await
tester
.
tap
(
find
.
text
(
'5'
));
await
tester
.
pumpAndSettle
();
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
AUGUST
,
5
)));
await
tester
.
pump
(
const
Duration
(
seconds:
2
));
await
tester
.
drag
(
find
.
byKey
(
_datePickerKey
),
const
Offset
(-
3
00.0
,
0.0
));
await
tester
.
pumpAndSettle
(
const
Duration
(
milliseconds:
100
)
);
await
tester
.
drag
(
find
.
byKey
(
_datePickerKey
),
const
Offset
(-
4
00.0
,
0.0
));
await
tester
.
pumpAndSettle
();
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
AUGUST
,
5
)));
await
tester
.
tapAt
(
const
Offset
(
45.0
,
270.0
));
await
tester
.
tap
(
find
.
text
(
'25'
));
await
tester
.
pumpAndSettle
();
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
SEPTEMBER
,
25
)));
await
tester
.
pump
(
const
Duration
(
seconds:
2
));
await
tester
.
drag
(
find
.
byKey
(
_datePickerKey
),
const
Offset
(
3
00.0
,
0.0
));
await
tester
.
pumpAndSettle
(
const
Duration
(
milliseconds:
100
)
);
await
tester
.
drag
(
find
.
byKey
(
_datePickerKey
),
const
Offset
(
8
00.0
,
0.0
));
await
tester
.
pumpAndSettle
();
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
SEPTEMBER
,
25
)));
await
tester
.
tapAt
(
const
Offset
(
210.0
,
180.0
));
await
tester
.
tap
(
find
.
text
(
'17'
));
await
tester
.
pumpAndSettle
();
expect
(
_selectedDate
,
equals
(
new
DateTime
(
2016
,
DateTime
.
AUGUST
,
17
)));
});
testWidgets
(
'render picker with intrinsic dimensions'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Overlay
(
initialEntries:
<
OverlayEntry
>[
new
OverlayEntry
(
builder:
(
BuildContext
context
)
=>
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
new
IntrinsicWidth
(
child:
new
IntrinsicHeight
(
child:
new
Material
(
child:
new
SingleChildScrollView
(
child:
new
MonthPicker
(
firstDate:
new
DateTime
(
0
),
lastDate:
new
DateTime
(
9999
),
onChanged:
(
DateTime
value
)
{
},
selectedDate:
new
DateTime
(
2000
,
DateTime
.
JANUARY
,
1
),
),
),
new
MaterialApp
(
home:
new
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
return
new
IntrinsicWidth
(
child:
new
IntrinsicHeight
(
child:
new
Material
(
child:
new
SingleChildScrollView
(
child:
new
MonthPicker
(
firstDate:
new
DateTime
(
0
),
lastDate:
new
DateTime
(
9999
),
onChanged:
(
DateTime
value
)
{
},
selectedDate:
new
DateTime
(
2000
,
DateTime
.
JANUARY
,
1
),
),
),
)
;
}
,
)
,
)
,
]
,
)
,
)
,
)
;
}
,
)
,
),
);
await
tester
.
pump
(
const
Duration
(
seconds:
5
));
...
...
packages/flutter/test/widgets/locale_query_test.dart
deleted
100644 → 0
View file @
7676e511
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/widgets.dart'
;
class
TestLocaleQueryData
extends
LocaleQueryData
{
@override
String
toString
()
=>
'Test data'
;
}
void
main
(
)
{
testWidgets
(
'LocaleQuery control test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Container
());
expect
(
LocaleQuery
.
of
(
tester
.
element
(
find
.
byType
(
Container
))),
isNull
);
final
LocaleQueryData
data
=
new
TestLocaleQueryData
();
final
Widget
widget
=
new
LocaleQuery
(
data:
data
,
child:
new
Container
(),
);
expect
(
widget
,
hasOneLineDescription
);
expect
(
widget
.
toString
(),
contains
(
'Test data'
));
await
tester
.
pumpWidget
(
widget
);
expect
(
LocaleQuery
.
of
(
tester
.
element
(
find
.
byType
(
Container
))),
equals
(
data
));
});
}
packages/flutter/test/widgets/localizations_test.dart
0 → 100644
View file @
8c2c5022
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment